我正在开发以下函数:extract_name_value() 生成一个采用 Python 中 Pandas DataFrame 值的步骤图,现在它工作正常,但我想在每个标记中添加变量 points_axisyvalue 或 values_list 的值:Script Here
我尝试使用以下示例:Data value at each marker , Matplotlib scatter plot with different text at each data point或 How to put individual tags for a matplotlib scatter plot? ,这将是我想要的东西;我什至尝试使用 plt.annotate()
,但是值的数据并没有按照我想要的方式出现,而且我认为它会掩盖图形很多并且不能很好地欣赏。下面我放了我使用 plt.annotate() 的代码:
# Function to extract the Name and Value attributes
def extract_name_value(signals_df, rootXML):
# print(signals_df)
names_list = [name for name in signals_df['Name'].unique()]
num_names_list = len(names_list)
num_axisx = len(signals_df["Name"])
values_list = [value for pos, value in enumerate(signals_df["Value"])]
print(values_list)
points_axisy = signals_df["Value"]
print(len(points_axisy))
colors = ['b', 'g', 'r', 'c', 'm', 'y']
# Creation Graphic
fig, ax = plt.subplots(nrows=num_names_list, figsize=(20, 30), sharex=True)
plt.suptitle(f'File XML: {rootXML}', fontsize=16, fontweight='bold', color='SteelBlue', position=(0.75, 0.95))
plt.xticks(np.arange(-1, num_axisx), color='SteelBlue', fontweight='bold')
labels = ['value: {0}'.format(j) for j in values_list]
print(labels)
i = 1
for pos, name in enumerate(names_list):
# get data
data = signals_df[signals_df["Name"] == name]["Value"]
print(data)
# get color
j = random.randint(0, len(colors) - 1)
# get plots by index = pos
x = np.hstack([-1, data.index.values, len(signals_df) - 1])
y = np.hstack([0, data.values, data.iloc[-1]])
ax[pos].plot(x, y, drawstyle='steps-post', marker='o', color=colors[j], linewidth=3)
ax[pos].set_ylabel(name, fontsize=8, fontweight='bold', color='SteelBlue', rotation=30, labelpad=35)
ax[pos].yaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))
ax[pos].yaxis.set_tick_params(labelsize=6)
ax[pos].grid(alpha=0.4)
i += 1
for label, x, y in zip(labels, x, y):
plt.annotate(label, xy=(x, y), xytext=(-20, 20), textcoords='offset points', ha='right', va='bottom', bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.5),
arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0'))
plt.show()
我得到的是拼接的和在不同位置的注释。但是,我的代码需要在每个点显示每个值吗?
我也一直在尝试使用 Matplotlib 引用中的代码,但无法完成:Marker Reference .非常感谢您,任何评论都有帮助。
最佳答案
您可以使用 plt.annotate循环运行以解决您的问题。
我随机生成了一些数据并将其绘制为单个图。你可以在子图中做同样的事情,功能是一样的。
# sample data points for the plot
x=np.arange(1,10)
y=np.linspace(20,40,9)
plt.figure(figsize=[15,5],dpi=200)
plt.plot(x,y,drawstyle='steps-post', marker='o')
# using annotate function to show the changepoints in a loop
for i in range(len(x)):
# I rounded the y values as string and used the same x and y coords as the locations
# next we can give a constant offset points to offset the annotation from each value
# here I used (-20,20) as the offset values
plt.annotate(f"{str(round((y[i])))}",(x[i],y[i]),xycoords='data',
xytext=(-20,20), textcoords='offset points',color="r",fontsize=12,
arrowprops=dict(arrowstyle="->", color='black'))
如果您不想要箭头,可以移除箭头 Prop 。已编辑
我用了
example1.xml
在您的 GitHub 存储库中创建文件并稍微编辑该函数。我所做的只是在您的函数中添加一个循环和一个 if-else 条件。# Initial part is same as yours
names_list = [name for name in signals_df['Name'].unique()]
num_names_list = len(names_list)
num_axisx = len(signals_df["Name"])
values_list = [value for pos, value in enumerate(signals_df["Value"])]
points_axisy = signals_df["Value"]
colors = ['b', 'g', 'r', 'c', 'm', 'y']
# start new figure
plt.figure(figsize=[20,28],dpi=200)
#start a loop with the subplots
for i in range(len(names_list)):
# subplot has 14 rows, 1 column and the i+1 represents the i'th plot
plt.subplot(num_names_list,1,i+1)
# choose color
col=np.random.randint(0, len(colors) - 1)
# get the locations of the values with the similar name in your list
locs=signals_df['Name']==names_list[i]
# get the values in those locations
data=signals_df['Value'][locs]
# arrange the x and y coordinates
x = np.hstack([-1, data.index.values, len(signals_df) - 1])
y = np.hstack([0, data.values, data.iloc[-1]])
# plot the values as usual
plt.plot(x, y, drawstyle='steps-post', marker='o', color=colors[col], linewidth=3)
plt.ylabel(names_list[i], fontsize=8, fontweight='bold', color='SteelBlue', rotation=30, labelpad=35)
plt.grid(alpha=0.4)
# this loop is for annotating the values
for j in range(len(x)):
# I found it is better to alternate the position of the annotations
# so that they wont overlap for the adjacent values
if j%2==0:
# In this condition the xytext position is (-20,20)
# this posts the annotation box over the plot value
plt.annotate(f"Val={round((y[j]))}",(x[j],y[j]),xycoords='data',
xytext=(-20,20), textcoords='offset points',color="r",fontsize=8,
arrowprops=dict(arrowstyle="->", color='black'),
bbox=dict(boxstyle='round', pad=0.5, fc='yellow', alpha=0.5))
else:
# In this condition the xytext position is (-20,-20)
# this posts the annotation box under the plot value
plt.annotate(f"Val={round((y[j]))}",(x[j],y[j]),xycoords='data',
xytext=(-20,-20), textcoords='offset points',color="r",fontsize=8,
arrowprops=dict(arrowstyle="->", color='black'),
bbox=dict(boxstyle='round', pad=0.5, fc='yellow', alpha=0.5))
新函数结果我希望它有用。
关于python - 子图中每个标记中变量的数据值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68276098/