ম্যাটপ্লটলিবের কোনও বিন্দুতে ঘোরাফেরা করার পরে লেবেল উপস্থিত হওয়া সম্ভব?


147

আমি স্ক্যাটার প্লট করতে ম্যাটপ্লটলিব ব্যবহার করছি। স্ক্যাটার প্লটের প্রতিটি পয়েন্ট একটি নামযুক্ত বস্তুর সাথে সম্পর্কিত। আমি যখন কোনও বিষয়টির সাথে যুক্ত ছড়িয়ে ছিটিয়ে থাকা প্লটটিতে আমার কার্সারটি পয়েন্টের উপরে রেখে দিচ্ছি তখন আমি কোনও বস্তুর নাম দেখতে সক্ষম হতে চাই। বিশেষত, বিদেশী যে পয়েন্টগুলির নাম দ্রুত তা জানতে সক্ষম হয়ে ভাল লাগবে। এখানে অনুসন্ধানের সময় আমি যে নিকটতম জিনিসটি সন্ধান করতে পেরেছি তা হ'ল এনোটেট কমান্ড, তবে এটি প্লটের উপর একটি স্থির লেবেল তৈরি করে বলে মনে হচ্ছে। দুর্ভাগ্যক্রমে, আমার যে পয়েন্টগুলির সংখ্যা রয়েছে তার সাথে, আমি প্রতিটি পয়েন্টকে লেবেল দিলে স্ক্যাটার প্লটটি অপঠনযোগ্য হবে। লেবেলগুলি তৈরি করার কোনও উপায় কি কেউ জানেন যে কেবল তখনই প্রদর্শিত হয় যখন কার্সারটি পয়েন্টের আশেপাশে ঘুরে বেড়ায়?


2
অনুসন্ধানের মাধ্যমে এখানে শেষ হওয়া লোকেরা এই উত্তরটি যাচাই করতে চাইতে পারে, এটি বরং জটিল, তবে প্রয়োজনীয়তার উপর নির্ভর করে উপযুক্ত হতে পারে।
ImportanceOfBeingEnnest

উত্তর:


133

দেখে মনে হচ্ছে এখানে অন্য উত্তরগুলির কোনওটিরই আসলে প্রশ্নের উত্তর নেই। সুতরাং এখানে একটি কোড যা একটি স্ক্যাটার ব্যবহার করে এবং স্ক্যাটার পয়েন্টগুলির উপরে ঘোরাফেরা করার উপর একটি টীকা দেখায় ।

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)

x = np.random.rand(15)
y = np.random.rand(15)
names = np.array(list("ABCDEFGHIJKLMNO"))
c = np.random.randint(1,5,size=15)

norm = plt.Normalize(1,4)
cmap = plt.cm.RdYlGn

fig,ax = plt.subplots()
sc = plt.scatter(x,y,c=c, s=100, cmap=cmap, norm=norm)

annot = ax.annotate("", xy=(0,0), xytext=(20,20),textcoords="offset points",
                    bbox=dict(boxstyle="round", fc="w"),
                    arrowprops=dict(arrowstyle="->"))
annot.set_visible(False)

def update_annot(ind):

    pos = sc.get_offsets()[ind["ind"][0]]
    annot.xy = pos
    text = "{}, {}".format(" ".join(list(map(str,ind["ind"]))), 
                           " ".join([names[n] for n in ind["ind"]]))
    annot.set_text(text)
    annot.get_bbox_patch().set_facecolor(cmap(norm(c[ind["ind"][0]])))
    annot.get_bbox_patch().set_alpha(0.4)


def hover(event):
    vis = annot.get_visible()
    if event.inaxes == ax:
        cont, ind = sc.contains(event)
        if cont:
            update_annot(ind)
            annot.set_visible(True)
            fig.canvas.draw_idle()
        else:
            if vis:
                annot.set_visible(False)
                fig.canvas.draw_idle()

fig.canvas.mpl_connect("motion_notify_event", hover)

plt.show()

এখানে চিত্র বর্ণনা লিখুন

যেহেতু লোকেরাও এই সমাধানটি একটি বিচ্ছুরের plotপরিবর্তে লাইনের জন্য ব্যবহার করতে চায় , নিম্নলিখিতগুলির জন্য একই সমাধান হবে plot(যা কিছুটা ভিন্নভাবে কাজ করে)।

যদি কেউ দুটি অক্ষরেখার জন্য লাইনগুলির সমাধানের সন্ধান করে তবে একাধিক অক্ষের একটি বিন্দুতে ঘোরাফেরা করার সময় কীভাবে লেবেলগুলি উপস্থিত হবে তা দেখুন?

যদি কেউ বার প্লটের সমাধানের সন্ধান করে তবে দয়া করে এই উত্তরটি দেখুন


1
খুব সুন্দর! একটি নোট, আমি লক্ষ করেছি যে ind["ind"]আসলে কর্সারের অধীনে সমস্ত পয়েন্টের জন্য সূচকের তালিকা। এর অর্থ হল যে উপরের কোডটি আপনাকে একটি নির্দিষ্ট অবস্থানে সমস্ত পয়েন্টগুলিতে অ্যাক্সেস দেয় এবং কেবল শীর্ষস্থানীয় পয়েন্ট নয়। উদাহরণস্বরূপ, আপনার যদি দুটি ওভারল্যাপিং পয়েন্ট থাকে তবে পাঠ্যটি পড়তে 1 2, B Cপারে 1 2 3, B C Dঅথবা আপনার কাছে 3 ওভারল্যাপিং পয়েন্ট রয়েছে।
জভিনভিয়েক

@ জভিনিয়াক ঠিক বলেছেন, উপরের চক্রান্তে ইচ্ছাকৃতভাবে এরকম একটি ঘটনা রয়েছে (x ~ 0.4-এ সবুজ এবং লাল বিন্দু)। যদি আপনি এটি হোভার করেন তবে এটি প্রদর্শিত হবে 0 8, A I, ( চিত্র দেখুন )।
ImportanceOfBeingEnnest

@ ইমপোর্টান্সঅফবিজিং আর্নেষ্ট এটি দুর্দান্ত কোড, তবে ঘোরাফেরা করে এবং কোনও পয়েন্টে চলার সময় এটি fig.canvas.draw_idle()বহুবার কল করে (এটি কার্সারটিকে নিষ্ক্রিয়তেও পরিবর্তন করে)। আমি পূর্ববর্তী সূচকটি সংরক্ষণ করে এটি পরীক্ষা করেছিলাম কিনা ind["ind"][0] == prev_ind। তারপরে কেবল আপডেট করুন যদি আপনি এক বিন্দু থেকে অন্য বিন্দুতে যান (আপডেট পাঠ্য), ঘোরা বন্ধ করুন (টীকাটি অদৃশ্য করুন) বা ঘোরা শুরু করুন (টীকাটি দৃশ্যমান করুন)। এই পরিবর্তনের সাথে এটি আরও পরিষ্কার এবং দক্ষ।
সেম্বেই নোরিমাকি

3
@ কনস্ট্যান্টিন হ্যাঁ %matplotlib notebookআইপিথন / জুপিটার নোটবুক ব্যবহার করার সময় এই সমাধানটি কার্যকর হবে ।
ImportanceOfBeingEnnest

1
@ ওরিওলআরবিল (এবং অন্য সবাই), এই উত্তর থেকে কোডটি সংশোধন করার সময় যদি আপনার কোন সমস্যা দেখা দেয় তবে দয়া করে এ সম্পর্কে একটি প্রশ্ন জিজ্ঞাসা করুন, এই উত্তরের সাথে লিঙ্ক করুন এবং আপনার চেষ্টা করা কোডটি দেখান। আপনার প্রতিটি কোডটি আসলে এটি না দেখে কী হয় তা জানার আমার কোনও উপায় নেই।
ImportanceOfBeingEnnest

66

কোনও লাইন ক্লিক করার প্রয়োজন ছাড়াই ঘোরাঘুরি করার সময় এই সমাধানটি কাজ করে:

import matplotlib.pyplot as plt

# Need to create as global variable so our callback(on_plot_hover) can access
fig = plt.figure()
plot = fig.add_subplot(111)

# create some curves
for i in range(4):
    # Giving unique ids to each data member
    plot.plot(
        [i*1,i*2,i*3,i*4],
        gid=i)

def on_plot_hover(event):
    # Iterating over each data member plotted
    for curve in plot.get_lines():
        # Searching which data member corresponds to current mouse position
        if curve.contains(event)[0]:
            print "over %s" % curve.get_gid()

fig.canvas.mpl_connect('motion_notify_event', on_plot_hover)           
plt.show()

1
খুব দরকারী + 1ed। আপনার সম্ভবত এটি 'ডাবনো' করা দরকার কারণ মোশন_নোটাইফাইভেন্টটি বক্রাকার অঞ্চলের ভিতরে গতির জন্য পুনরাবৃত্তি করবে। কেবল বক্ররেখার বস্তুটি পূর্ববর্তী বক্ররেখার সমান যাচাই করে দেখা যাচ্ছে।
bvanlew

5
হুম - এই আমাকে (তাই কিছু বিষয় না জন্য আউট-অফ-বক্স কাজ করে নি matplotlib...) - সঙ্গে কাজ করে ipython/ jupyterনোটবুকের? একাধিক সাবপ্লট থাকলে এটি কি কাজ করে? লাইন-গ্রাফের চেয়ে বার-চার্টের কী হবে?
ডোয়ান্ডারসন

12
ঘোরাঘুরির সময় এটি কনসোলে লেবেলটি মুদ্রণ করে। ঘোরাঘুরি করার সময় লেবেলটি ছবিতে উপস্থিত হওয়া সম্পর্কে কী ? আমি বুঝতে হবে যে প্রশ্ন হতে।
নিকানা রেকলাভিক্স

@ অ্যামনারাসোচি অনেক ধন্যবাদ, আমি যদি হিস্টোগ্রাম (ছড়িয়ে ছিটিয়ে থাকা প্রতিটি পয়েন্টের জন্য আলাদা আলাদা) দেখতে চাই বা আরও ভাল, 2 ডি হিস্টোগ্রামের হিট-ম্যাপ দেখতে চাই তবে আমাকে কী যুক্তিতে ফিড দেওয়ার দরকার?
অমিতাই

@ নিকানারেকলাভিক্স আমি একটি উত্তর যুক্ত করেছি যা আসলে প্রশ্নের উত্তর দেয়।
ImportanceOfBeingEnnest

37

Http://matplotlib.sourceforge.net/example/event_handling/pick_event_demo.html থেকে :

from matplotlib.pyplot import figure, show
import numpy as npy
from numpy.random import rand


if 1: # picking on a scatter plot (matplotlib.collections.RegularPolyCollection)

    x, y, c, s = rand(4, 100)
    def onpick3(event):
        ind = event.ind
        print('onpick3 scatter:', ind, npy.take(x, ind), npy.take(y, ind))

    fig = figure()
    ax1 = fig.add_subplot(111)
    col = ax1.scatter(x, y, 100*s, c, picker=True)
    #fig.savefig('pscoll.eps')
    fig.canvas.mpl_connect('pick_event', onpick3)

show()

এটি আমার যা প্রয়োজন কেবল তা করে, আপনাকে ধন্যবাদ! বোনাস হিসাবে, এটি বাস্তবায়নের জন্য, আমি আমার প্রোগ্রামটি পুনরায় লিখেছিলাম যাতে দুটি চিত্রের দুটি সেট উপস্থাপনের জন্য একই চিত্রে পৃথক বর্ণে দুটি পৃথক স্ক্যাটার প্লট তৈরি করার পরিবর্তে, আমি বিন্দুতে বর্ণ নির্ধারণের জন্য উদাহরণটির পদ্ধতিটি অনুলিপি করেছিলাম। এটি আমার প্রোগ্রামটি পড়ার জন্য কিছুটা সহজ এবং কোডটি কম করেছে। কোনও সংখ্যায় রঙ রূপান্তর করার জন্য গাইড খুঁজে পেতে এখন বন্ধ!
jdmcbr

1
এটি বিক্ষিপ্ত প্লটের জন্য। লাইন প্লট সম্পর্কে কি? আমি তাদের উপর এটি কাজ করার চেষ্টা করেছি কিন্তু তা হয় না। কোন কর্মশালা আছে?
সোহাইব

@ সোহাইব আমার উত্তরটি দেখুন
টেক্সাসফ্লুড

আমি এই সম্পর্কে একটি প্রশ্ন আছে। আমি যখন আমার পয়েন্টগুলি এর মতো বিক্ষিপ্তভাবে প্লট করি: plt.scatter (X_reduced [y == i, 0], X_reduced [y == i, 1], c = c, লেবেল = লক্ষ্য_নাম, চয়নকারী = সত্য) এর জন্য একটি জিপ সহ i, c এবং টার্গেট_নাম, তাহলে কি আমার সূচকগুলির ক্রমটি গণ্ডগোল হয়? এবং আমি এটি আর কোন ডেটাপয়েন্ট নিয়োগের দিকে তাকাতে পারি না?
ক্রিস

এটি আইপথন 5 সহ জপিটার 5 নোটবুকের জন্য কাজ করছে বলে মনে হচ্ছে না that এটি ঠিক করার কোনও সহজ উপায় আছে কি? printবিবৃতি সাথে পাইথন 3 সামঞ্জস্যের জন্য ডান বন্ধনী ব্যবহার করা উচিত
nealmcb

14

Http://matplotlib.org/users/shell.html এ সরবরাহ করা একটি উদাহরণে একটি সামান্য সম্পাদনা :

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('click on points')

line, = ax.plot(np.random.rand(100), '-', picker=5)  # 5 points tolerance


def onpick(event):
    thisline = event.artist
    xdata = thisline.get_xdata()
    ydata = thisline.get_ydata()
    ind = event.ind
    print('onpick points:', *zip(xdata[ind], ydata[ind]))


fig.canvas.mpl_connect('pick_event', onpick)

plt.show()

সোহাইব যেমন জিজ্ঞাসা করছিলেন, তেমনি এই সরলরেখার প্লট রয়েছে


5

আমার জন্য এটি সমাধান করুন। সম্পাদনা (কোড সংযোজন):

import matplotlib.pyplot as plt
import numpy as np
import mpld3

fig, ax = plt.subplots(subplot_kw=dict(axisbg='#EEEEEE'))
N = 100

scatter = ax.scatter(np.random.normal(size=N),
                 np.random.normal(size=N),
                 c=np.random.random(size=N),
                 s=1000 * np.random.random(size=N),
                 alpha=0.3,
                 cmap=plt.cm.jet)
ax.grid(color='white', linestyle='solid')

ax.set_title("Scatter Plot (with tooltips!)", size=20)

labels = ['point {0}'.format(i + 1) for i in range(N)]
tooltip = mpld3.plugins.PointLabelTooltip(scatter, labels=labels)
mpld3.plugins.connect(fig, tooltip)

mpld3.show()

আপনি এই উদাহরণটি পরীক্ষা করতে পারেন


দয়া করে নমুনা কোড অন্তর্ভুক্ত করুন এবং কোনও প্রসঙ্গ বা তথ্য ছাড়া কেবল বাহ্যিক উত্সগুলিতে লিঙ্ক করবেন না। দেখুন সহায়তা কেন্দ্র দেখুন।
জোসেফ ফারাহ

5
দুর্ভাগ্যক্রমে এমপিএলডি 3 আর সক্রিয়ভাবে জুলাই 2017 পর্যন্ত রক্ষণাবেক্ষণ করা হচ্ছে না
বেন লিন্ডসে

কোড নমুনা একটি সঙ্গে ব্যর্থ TypeError: array([1.]) is not JSON serializable
পি-জিএন

@ পি-জিএন শুধু কৌতুক এখানে অনুসরণ stackoverflow.com/questions/48015030/mpld3-with-python-error MPLD3 এই জন্য একটি সহজ সমাধান এবং একবার উপরে উত্তর অনুসরণ করা হয়, এটি কাজ করে।
জালাকাইন

1
@ জালাকাইন দুর্ভাগ্যক্রমে, এমপিএল 3 ডি পরিত্যক্ত বলে মনে হচ্ছে
পি-জিএন

5

mplcursors আমার জন্য কাজ করেছে। এমপিএলকার্সারগুলি ম্যাটপ্ল্লটিবের জন্য ক্লিকযোগ্য টীকা সরবরাহ করে। এটি এমপিএলডাটাকসর ( https://github.com/joferkington/mpldatacursor ) থেকে প্রচুর সরলীকৃত এপিআই সহ ভারীভাবে অনুপ্রাণিত

import matplotlib.pyplot as plt
import numpy as np
import mplcursors

data = np.outer(range(10), range(1, 5))

fig, ax = plt.subplots()
lines = ax.plot(data)
ax.set_title("Click somewhere on a line.\nRight-click to deselect.\n"
             "Annotations can be dragged.")

mplcursors.cursor(lines) # or just mplcursors.cursor()

plt.show()

আমি নিজেই এটি ব্যবহার করি, তাড়াহুড়োয় কারও পক্ষে সবচেয়ে সহজ সমাধান। আমি সবেমাত্র 70 টি লেবেল প্লট করেছি এবং matplotlibপ্রতি 10 তম লাইনকে একই রঙে তৈরি করি, যেমন একটি ব্যথা। mplcursorsযদিও এটি সাজানোর।
এজেএসপি

5

অন্যান্য উত্তরগুলি জুপির ইনলাইন ম্যাটপ্ল্লিটব চিত্রের সাম্প্রতিক সংস্করণে টুলটিপগুলি সঠিকভাবে প্রদর্শন করার জন্য আমার প্রয়োজনীয়তার দিকে নজর দেয়নি। এটি যদিও কাজ করে:

import matplotlib.pyplot as plt
import numpy as np
import mplcursors
np.random.seed(42)

fig, ax = plt.subplots()
ax.scatter(*np.random.random((2, 26)))
ax.set_title("Mouse over a point")
crs = mplcursors.cursor(ax,hover=True)

crs.connect("add", lambda sel: sel.annotation.set_text(
    'Point {},{}'.format(sel.target[0], sel.target[1])))
plt.show()

মাউসের সাহায্যে একটি বিন্দুতে যাওয়ার সময় নীচের ছবির মতো কোনও কিছুর দিকে নিয়ে যাওয়া: এখানে চিত্র বর্ণনা লিখুন



আমি এটি জ্য্যাপিটার ল্যাবে কাজ করতে পারি না। এটি সম্ভবত জুপিটার নোটবুকে কাজ করে তবে জুপিটার ল্যাবে নেই?
MD004

3

আপনি যদি জপিটার নোটবুক ব্যবহার করেন তবে আমার সমাধানটি যত সহজ:

%pylab
import matplotlib.pyplot as plt
import mplcursors
plt.plot(...)
mplcursors.cursor(hover=True)
plt.show()

আপনি কিছু পেতে পারেন এখানে চিত্র বর্ণনা লিখুন


এখন পর্যন্ত সর্বোত্তম সমাধান, কেবল কয়েকটি লাইনের কোড ওপি যা চেয়েছিল ঠিক তাই করে
টিম জনসেন

0

আমি এতে যুক্ত করার জন্য একটি বহু-লাইন এনোটেশন সিস্টেম তৈরি করেছি: https://stackoverflow.com/a/47166787/10302020 । সর্বাধিক আপ টু ডেট সংস্করণ: https://github.com/AidenBurgess/ মাল্টিএন্টোটেশনলাইনগ্রাফ

কেবল নীচের অংশে ডেটা পরিবর্তন করুন।

import matplotlib.pyplot as plt


def update_annot(ind, line, annot, ydata):
    x, y = line.get_data()
    annot.xy = (x[ind["ind"][0]], y[ind["ind"][0]])
    # Get x and y values, then format them to be displayed
    x_values = " ".join(list(map(str, ind["ind"])))
    y_values = " ".join(str(ydata[n]) for n in ind["ind"])
    text = "{}, {}".format(x_values, y_values)
    annot.set_text(text)
    annot.get_bbox_patch().set_alpha(0.4)


def hover(event, line_info):
    line, annot, ydata = line_info
    vis = annot.get_visible()
    if event.inaxes == ax:
        # Draw annotations if cursor in right position
        cont, ind = line.contains(event)
        if cont:
            update_annot(ind, line, annot, ydata)
            annot.set_visible(True)
            fig.canvas.draw_idle()
        else:
            # Don't draw annotations
            if vis:
                annot.set_visible(False)
                fig.canvas.draw_idle()


def plot_line(x, y):
    line, = plt.plot(x, y, marker="o")
    # Annotation style may be changed here
    annot = ax.annotate("", xy=(0, 0), xytext=(-20, 20), textcoords="offset points",
                        bbox=dict(boxstyle="round", fc="w"),
                        arrowprops=dict(arrowstyle="->"))
    annot.set_visible(False)
    line_info = [line, annot, y]
    fig.canvas.mpl_connect("motion_notify_event",
                           lambda event: hover(event, line_info))


# Your data values to plot
x1 = range(21)
y1 = range(0, 21)
x2 = range(21)
y2 = range(0, 42, 2)
# Plot line graphs
fig, ax = plt.subplots()
plot_line(x1, y1)
plot_line(x2, y2)
plt.show()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.