mplcursors 与散点图端点的交互
mplcursors interactivity with endpoints of scatterplots
import pandas as pd
import matplotlib.pyplot as plt
import mplcursors
df = pd.DataFrame(
{'Universe': ['Darvel', 'MC', 'MC', 'Darvel', 'MC', 'Other', 'Darvel'],
'Value': [10, 11, 13, 12, 9, 7, 10],
'Upper': [12.5, 11.3, 15.4, 12.2, 13.1, 8.8, 11.5],
'Lower': [4.5, 9.6, 11.8, 6, 6.5, 5, 8]})
df['UpperError'] = df['Upper'] - df['Value']
df['LowerError'] = df['Value'] - df['Lower']
colors = ['r', 'g', 'b']
fig, ax = plt.subplots()
for i, universe in enumerate(df['Universe'].unique()):
to_plot = df[df['Universe'] == universe]
ax.scatter(to_plot.index, to_plot['Value'], s=16, c=colors[i])
error = to_plot[['LowerError', 'UpperError']].transpose().to_numpy()
ax.errorbar(to_plot.index, to_plot['Value'], yerr=error, fmt='o',
markersize=0, capsize=6, color=colors[i])
ax.scatter(to_plot.index, to_plot['Upper'], c='w', zorder=-1)
ax.scatter(to_plot.index, to_plot['Lower'], c='w', zorder=-1)
mplcursors.cursor(hover=True)
plt.show()
这完成了大部分我想要的,但我想要以下更改。
我不希望 mplcursors 光标与误差线交互,而只是散点图,包括误差线顶部和底部的不可见散点图。
我只想显示 y 值。例如,第一个小节应该在顶部显示“12.5”,在中间显示“10.0”,在底部显示“4.5”。
要让 mplcursors 仅与某些元素交互,可以将这些元素的列表作为第一个参数提供给 mplcursors.cursor()
。该列表可以根据对 ax.scatter
.
的调用的 return 值构建
要修改显示的注释文本,可以连接自定义函数。在下面的示例中,标签和 y 位置从所选元素中提取并放入注释文本中。可以通过 ax.scatter(..., label=...)
.
添加此类标签
(选择 'none'
作为“不可见”元素的颜色使它们真正不可见。为了使代码更 可以避免显式索引,而是使用 zip
enumerate
.)
import matplotlib.pyplot as plt
import mplcursors
import pandas as pd
def show_annotation(sel):
text = f'{sel.artist.get_label()}\n y={sel.target[1]:.1f}'
sel.annotation.set_text(text)
df = pd.DataFrame(
{'Universe': ['Darvel', 'MC', 'MC', 'Darvel', 'MC', 'Other', 'Darvel'],
'Value': [10, 11, 13, 12, 9, 7, 10],
'Upper': [12.5, 11.3, 15.4, 12.2, 13.1, 8.8, 11.5],
'Lower': [4.5, 9.6, 11.8, 6, 6.5, 5, 8]})
df['UpperError'] = df['Upper'] - df['Value']
df['LowerError'] = df['Value'] - df['Lower']
colors = ['r', 'g', 'b']
fig, ax = plt.subplots()
all_scatters = []
for universe, color in zip(df['Universe'].unique(), colors):
to_plot = df[df['Universe'] == universe]
all_scatters.append(ax.scatter(to_plot.index, to_plot['Value'], s=16, c=color, label=universe))
error = to_plot[['LowerError', 'UpperError']].transpose().to_numpy()
ax.errorbar(to_plot.index, to_plot['Value'], yerr=error, fmt='o',
markersize=0, capsize=6, color=color)
all_scatters.append(ax.scatter(to_plot.index, to_plot['Upper'], c='none', zorder=-1, label=universe))
all_scatters.append(ax.scatter(to_plot.index, to_plot['Lower'], c='none', zorder=-1, label=universe))
cursor = mplcursors.cursor(all_scatters, hover=True)
cursor.connect('add', show_annotation)
plt.show()
PS:您还可以通过 x 刻度显示 'Universe'
:
ax.set_xticks(df.index)
ax.set_xticklabels(df['Universe'])
如果您愿意,对于短函数,您可以使用 lambda 表示法而不是编写单独的函数:
cursor.connect('add',
lambda sel: sel.annotation.set_text(f'{sel.artist.get_label()}\n y={sel.target[1]:.1f}'))
import pandas as pd
import matplotlib.pyplot as plt
import mplcursors
df = pd.DataFrame(
{'Universe': ['Darvel', 'MC', 'MC', 'Darvel', 'MC', 'Other', 'Darvel'],
'Value': [10, 11, 13, 12, 9, 7, 10],
'Upper': [12.5, 11.3, 15.4, 12.2, 13.1, 8.8, 11.5],
'Lower': [4.5, 9.6, 11.8, 6, 6.5, 5, 8]})
df['UpperError'] = df['Upper'] - df['Value']
df['LowerError'] = df['Value'] - df['Lower']
colors = ['r', 'g', 'b']
fig, ax = plt.subplots()
for i, universe in enumerate(df['Universe'].unique()):
to_plot = df[df['Universe'] == universe]
ax.scatter(to_plot.index, to_plot['Value'], s=16, c=colors[i])
error = to_plot[['LowerError', 'UpperError']].transpose().to_numpy()
ax.errorbar(to_plot.index, to_plot['Value'], yerr=error, fmt='o',
markersize=0, capsize=6, color=colors[i])
ax.scatter(to_plot.index, to_plot['Upper'], c='w', zorder=-1)
ax.scatter(to_plot.index, to_plot['Lower'], c='w', zorder=-1)
mplcursors.cursor(hover=True)
plt.show()
这完成了大部分我想要的,但我想要以下更改。
我不希望 mplcursors 光标与误差线交互,而只是散点图,包括误差线顶部和底部的不可见散点图。
我只想显示 y 值。例如,第一个小节应该在顶部显示“12.5”,在中间显示“10.0”,在底部显示“4.5”。
要让 mplcursors 仅与某些元素交互,可以将这些元素的列表作为第一个参数提供给 mplcursors.cursor()
。该列表可以根据对 ax.scatter
.
要修改显示的注释文本,可以连接自定义函数。在下面的示例中,标签和 y 位置从所选元素中提取并放入注释文本中。可以通过 ax.scatter(..., label=...)
.
(选择 'none'
作为“不可见”元素的颜色使它们真正不可见。为了使代码更 zip
enumerate
.)
import matplotlib.pyplot as plt
import mplcursors
import pandas as pd
def show_annotation(sel):
text = f'{sel.artist.get_label()}\n y={sel.target[1]:.1f}'
sel.annotation.set_text(text)
df = pd.DataFrame(
{'Universe': ['Darvel', 'MC', 'MC', 'Darvel', 'MC', 'Other', 'Darvel'],
'Value': [10, 11, 13, 12, 9, 7, 10],
'Upper': [12.5, 11.3, 15.4, 12.2, 13.1, 8.8, 11.5],
'Lower': [4.5, 9.6, 11.8, 6, 6.5, 5, 8]})
df['UpperError'] = df['Upper'] - df['Value']
df['LowerError'] = df['Value'] - df['Lower']
colors = ['r', 'g', 'b']
fig, ax = plt.subplots()
all_scatters = []
for universe, color in zip(df['Universe'].unique(), colors):
to_plot = df[df['Universe'] == universe]
all_scatters.append(ax.scatter(to_plot.index, to_plot['Value'], s=16, c=color, label=universe))
error = to_plot[['LowerError', 'UpperError']].transpose().to_numpy()
ax.errorbar(to_plot.index, to_plot['Value'], yerr=error, fmt='o',
markersize=0, capsize=6, color=color)
all_scatters.append(ax.scatter(to_plot.index, to_plot['Upper'], c='none', zorder=-1, label=universe))
all_scatters.append(ax.scatter(to_plot.index, to_plot['Lower'], c='none', zorder=-1, label=universe))
cursor = mplcursors.cursor(all_scatters, hover=True)
cursor.connect('add', show_annotation)
plt.show()
PS:您还可以通过 x 刻度显示 'Universe'
:
ax.set_xticks(df.index)
ax.set_xticklabels(df['Universe'])
如果您愿意,对于短函数,您可以使用 lambda 表示法而不是编写单独的函数:
cursor.connect('add',
lambda sel: sel.annotation.set_text(f'{sel.artist.get_label()}\n y={sel.target[1]:.1f}'))