আপডেট: ব্যবহারকারী সিএফাইক এই উত্তরটিতে কোডটির জন্য দয়া করে একটি গিথুব সংগ্রহশালা তৈরি করেছেন (দেখুন এখানে ) এবং কোডটি একটি প্যাকেজে বান্ডিল করেছে যা ব্যবহার করে ইনস্টল করা হতে পারে pip install matplotlib-label-lines
।
সুন্দর ছবি:
এতে কনট্যুর প্লটগুলি লেবেল করাmatplotlib
বেশ সহজ (হয় স্বয়ংক্রিয়ভাবে বা ম্যানুয়ালি ক্লিক দিয়ে ম্যানুয়ালি লেবেল রেখে)। এই ফ্যাশনে ডেটা সিরিজ লেবেল করার জন্য (এখনও) কোনও সমমানের সামর্থ্য বলে মনে হয় না! এই বৈশিষ্ট্যটি অন্তর্ভুক্ত না করার জন্য কিছু অর্থপূর্ণ কারণ থাকতে পারে।
নির্বিশেষে, আমি নিম্নলিখিত মডিউলটি লিখেছি যা আধা-স্বয়ংক্রিয় প্লট লেবেলিংয়ের জন্য কোনও অনুমতি নেয়। numpy
স্ট্যান্ডার্ড math
লাইব্রেরি থেকে এটির জন্য এবং কয়েকটি ফাংশন প্রয়োজন ।
বর্ণনা
labelLines
ফাংশনের ডিফল্ট আচরণটি হ'ল x
অক্ষগুলি বরাবর সমানভাবে লেবেলগুলিকে স্থান দেওয়া (স্বয়ংক্রিয়ভাবে y
অবশ্যই সঠিক- মূল্যকে রেখে দেওয়া )। আপনি যদি চান তবে কেবলমাত্র প্রতিটি লেবেলের এক্স কো-অর্ডিনেটের একটি অ্যারে পাস করতে পারেন। এমনকি আপনি একটি লেবেলের অবস্থানটি (এমনকি নীচের ডানদিকের প্লটটিতে দেখানো হয়েছে) ঝাঁকুনি করতে পারেন এবং আপনার পছন্দ মতো স্থানটিকে সমানভাবে স্থান দিতে পারেন।
তদুপরি, label_lines
ফাংশনটি লাইনগুলিতে হিসাব করে না যার plot
কমান্ডে লেবেল বরাদ্দ নেই (বা আরও সঠিকভাবে যদি লেবেলটি থাকে তবে '_line'
)।
কীওয়ার্ড আর্গুমেন্টগুলি ফাংশন কলটিতে পাস করা labelLines
বা labelLine
পাস করা হয় text
(কলিং কোডটি নির্দিষ্ট না করার জন্য কিছু কীওয়ার্ড আর্গুমেন্ট সেট করা থাকে)।
ইস্যু
- টীকাগুলির বাউন্ডিং বাক্সগুলি কখনও কখনও অন্যান্য কার্ভগুলির সাথে অনস্বীকার্যভাবে হস্তক্ষেপ করে। উপরের বাম চক্রান্তে টীকাগুলি
1
এবং 10
টীকাগুলি দ্বারা দেখানো হয়েছে । আমি এও নিশ্চিত না যে এড়ানো যায়।
- এটি
y
পরিবর্তে কখনও কখনও একটি অবস্থান নির্দিষ্ট করা ভাল হবে ।
- সঠিক স্থানে টিকা পেতে এটি এখনও পুনরাবৃত্তি প্রক্রিয়া
- এটা শুধুমাত্র কাজ করে
x
-axis মান float
গুলি
গটছস
- ডিফল্টরূপে,
labelLines
ফাংশনটি ধরে নিয়েছে যে সমস্ত ডেটা সিরিজ অক্ষ সীমা দ্বারা নির্দিষ্ট রেঞ্জের স্প্যান করে। সুন্দর ছবির উপরের বাম প্লটের নীল বক্ররেখায় একবার দেখুন। যদি এই x
ব্যাপ্তির জন্য কেবলমাত্র ডেটা উপলব্ধ ছিল 0.5
- 1
তবে আমরা সম্ভবত পছন্দসই স্থানে একটি লেবেল রাখতে পারিনি (যা এর চেয়ে কিছুটা কম 0.2
)। একটি বিশেষভাবে বাজে উদাহরণের জন্য এই প্রশ্নটি দেখুন । এখনই, কোডটি বুদ্ধিমানভাবে এই দৃশ্যটি সনাক্ত করতে পারে না এবং লেবেলগুলি পুনরায় সাজায় না, তবে যুক্তিসঙ্গত কাজ রয়েছে। লেবেলাইনস ফাংশনটি xvals
যুক্তিটি গ্রহণ করে ; x
প্রস্থ জুড়ে ডিফল্ট লিনিয়ার বিতরণের পরিবর্তে ব্যবহারকারী দ্বারা নির্ধারিত মূল্যগুলির একটি তালিকা । সুতরাং ব্যবহারকারী কোনটি সিদ্ধান্ত নিতে পারেx
প্রতিটি ডেটা সিরিজের লেবেল স্থাপনের জন্য ব্যবহারের মূল্য।
এছাড়াও, আমি বিশ্বাস করি যে লেবেলগুলি বদ্ধ রয়েছে তার সাথে সারিবদ্ধ করার বোনাস উদ্দেশ্যটি সম্পূর্ণ করার এটি প্রথম উত্তর । :)
লেবেল_লাইন.পি:
from math import atan2,degrees
import numpy as np
#Label line with line2D label data
def labelLine(line,x,label=None,align=True,**kwargs):
ax = line.axes
xdata = line.get_xdata()
ydata = line.get_ydata()
if (x < xdata[0]) or (x > xdata[-1]):
print('x label location is outside data range!')
return
#Find corresponding y co-ordinate and angle of the line
ip = 1
for i in range(len(xdata)):
if x < xdata[i]:
ip = i
break
y = ydata[ip-1] + (ydata[ip]-ydata[ip-1])*(x-xdata[ip-1])/(xdata[ip]-xdata[ip-1])
if not label:
label = line.get_label()
if align:
#Compute the slope
dx = xdata[ip] - xdata[ip-1]
dy = ydata[ip] - ydata[ip-1]
ang = degrees(atan2(dy,dx))
#Transform to screen co-ordinates
pt = np.array([x,y]).reshape((1,2))
trans_angle = ax.transData.transform_angles(np.array((ang,)),pt)[0]
else:
trans_angle = 0
#Set a bunch of keyword arguments
if 'color' not in kwargs:
kwargs['color'] = line.get_color()
if ('horizontalalignment' not in kwargs) and ('ha' not in kwargs):
kwargs['ha'] = 'center'
if ('verticalalignment' not in kwargs) and ('va' not in kwargs):
kwargs['va'] = 'center'
if 'backgroundcolor' not in kwargs:
kwargs['backgroundcolor'] = ax.get_facecolor()
if 'clip_on' not in kwargs:
kwargs['clip_on'] = True
if 'zorder' not in kwargs:
kwargs['zorder'] = 2.5
ax.text(x,y,label,rotation=trans_angle,**kwargs)
def labelLines(lines,align=True,xvals=None,**kwargs):
ax = lines[0].axes
labLines = []
labels = []
#Take only the lines which have labels other than the default ones
for line in lines:
label = line.get_label()
if "_line" not in label:
labLines.append(line)
labels.append(label)
if xvals is None:
xmin,xmax = ax.get_xlim()
xvals = np.linspace(xmin,xmax,len(labLines)+2)[1:-1]
for line,x,label in zip(labLines,xvals,labels):
labelLine(line,x,label,align,**kwargs)
উপরের সুন্দর ছবিটি তৈরি করার জন্য টেস্ট কোড:
from matplotlib import pyplot as plt
from scipy.stats import loglaplace,chi2
from labellines import *
X = np.linspace(0,1,500)
A = [1,2,5,10,20]
funcs = [np.arctan,np.sin,loglaplace(4).pdf,chi2(5).pdf]
plt.subplot(221)
for a in A:
plt.plot(X,np.arctan(a*X),label=str(a))
labelLines(plt.gca().get_lines(),zorder=2.5)
plt.subplot(222)
for a in A:
plt.plot(X,np.sin(a*X),label=str(a))
labelLines(plt.gca().get_lines(),align=False,fontsize=14)
plt.subplot(223)
for a in A:
plt.plot(X,loglaplace(4).pdf(a*X),label=str(a))
xvals = [0.8,0.55,0.22,0.104,0.045]
labelLines(plt.gca().get_lines(),align=False,xvals=xvals,color='k')
plt.subplot(224)
for a in A:
plt.plot(X,chi2(5).pdf(a*X),label=str(a))
lines = plt.gca().get_lines()
l1=lines[-1]
labelLine(l1,0.6,label=r'$Re=${}'.format(l1.get_label()),ha='left',va='bottom',align = False)
labelLines(lines[:-1],align=False)
plt.show()
plt.plot(x2, 3*x2**2, label="3x*x"); plt.plot(x2, 2*x2**2, label="2x*x"); plt.plot(x2, 0.5*x2**2, label="0.5x*x"); plt.plot(x2, -1*x2**2, label="-x*x"); plt.plot(x2, -2.5*x2**2, label="-2.5*x*x"); my_legend();
এটি উপরের বাম কোণে একটি লেবেল রাখে। এটি ঠিক করার জন্য কোনও ধারণা? সমস্যাটি দেখে মনে হচ্ছে সমস্যাগুলি লাইনগুলি খুব কাছাকাছি থাকতে পারে।