如何在遍历 pandas 数据帧时在 matplotlib 散点图中标记数据点?
How to label data points in matplotlib scatter plot while looping through pandas dataframes?
我有一个 pandas 数据框,包括以下列:
label = ('A' , 'D' , 'K', 'L', 'P')
x = (1 , 4 , 9, 6, 4)
y = (2 , 6 , 5, 8, 9)
plot_id = (1 , 1 , 2, 2, 3)
我想创建 3 个单独的散点图 - 每个人一个 plot_id
。所以第一个散点图应该包含 plot_id == 1
的所有条目,因此点 (1,2) 和 (4,6)。每个数据点应标记为 label
。因此第一个图应该有标签 A
和 B
.
我明白我可以用annotate
来标注,我熟悉for
循环。但是我不知道如何将两者结合起来。
我希望我可以 post 更好地展示我目前所做的代码片段 - 但它太糟糕了。这是:
for i in range(len(df.plot_id)):
plt.scatter(df.x[i],df.y[i])
plt.show()
这就是我的全部 - 不幸的是。关于如何进行的任何想法?
更新答案
保存单独的图像文件
def annotate(row, ax):
ax.annotate(row.label, (row.x, row.y),
xytext=(10, -5), textcoords='offset points')
for pid, grp in df.groupby('plot_id'):
ax = grp.plot.scatter('x', 'y')
grp.apply(annotate, ax=ax, axis=1)
plt.savefig('{}.png'.format(pid))
plt.close()
1.png
2.png
3.png
旧答案
对于那些想要这样的东西的人
def annotate(row, ax):
ax.annotate(row.label, (row.x, row.y),
xytext=(10, -5), textcoords='offset points')
fig, axes = plt.subplots(df.plot_id.nunique(), 1)
for i, (pid, grp) in enumerate(df.groupby('plot_id')):
ax = axes[i]
grp.plot.scatter('x', 'y', ax=ax)
grp.apply(annotate, ax=ax, axis=1)
fig.tight_layout()
设置
label = ('A' , 'D' , 'K', 'L', 'P')
x = (1 , 4 , 9, 6, 4)
y = (2 , 6 , 5, 8, 9)
plot_id = (1 , 1 , 2, 2, 3)
df = pd.DataFrame(dict(label=label, x=x, y=y, plot_id=plot_id))
这里有一个简单的方法来解决您的问题:
zipped = zip(zip(zip(df.x, df.y), df.plot_id), df.label)
# Result : [(((1, 2), 1), 'A'),
# (((4, 6), 1), 'D'),
# (((9, 5), 2), 'K'),
# (((6, 8), 2), 'L'),
# (((4, 9), 3), 'P')]
要检索位置、绘图索引和标签,您可以按以下方式循环:
for (pos, plot), label in zipped:
...
print pos
print plot
print label
现在您可以根据自己的情况执行以下操作:
import matplotlib.pyplot as plt
for (pos, plot), label in zipped:
plt.figure(plot)
x, y = pos
plt.scatter(x, y)
plt.annotate(label, xy=pos)
它将创建与 plot_ids
一样多的图形,并为每个图形显示具有相应 plot_ids
值的点的散点图。更重要的是,它会在每个点上覆盖标签。
我有一个 pandas 数据框,包括以下列:
label = ('A' , 'D' , 'K', 'L', 'P')
x = (1 , 4 , 9, 6, 4)
y = (2 , 6 , 5, 8, 9)
plot_id = (1 , 1 , 2, 2, 3)
我想创建 3 个单独的散点图 - 每个人一个 plot_id
。所以第一个散点图应该包含 plot_id == 1
的所有条目,因此点 (1,2) 和 (4,6)。每个数据点应标记为 label
。因此第一个图应该有标签 A
和 B
.
我明白我可以用annotate
来标注,我熟悉for
循环。但是我不知道如何将两者结合起来。
我希望我可以 post 更好地展示我目前所做的代码片段 - 但它太糟糕了。这是:
for i in range(len(df.plot_id)):
plt.scatter(df.x[i],df.y[i])
plt.show()
这就是我的全部 - 不幸的是。关于如何进行的任何想法?
更新答案
保存单独的图像文件
def annotate(row, ax):
ax.annotate(row.label, (row.x, row.y),
xytext=(10, -5), textcoords='offset points')
for pid, grp in df.groupby('plot_id'):
ax = grp.plot.scatter('x', 'y')
grp.apply(annotate, ax=ax, axis=1)
plt.savefig('{}.png'.format(pid))
plt.close()
1.png
2.png
3.png
旧答案
对于那些想要这样的东西的人
def annotate(row, ax):
ax.annotate(row.label, (row.x, row.y),
xytext=(10, -5), textcoords='offset points')
fig, axes = plt.subplots(df.plot_id.nunique(), 1)
for i, (pid, grp) in enumerate(df.groupby('plot_id')):
ax = axes[i]
grp.plot.scatter('x', 'y', ax=ax)
grp.apply(annotate, ax=ax, axis=1)
fig.tight_layout()
设置
label = ('A' , 'D' , 'K', 'L', 'P')
x = (1 , 4 , 9, 6, 4)
y = (2 , 6 , 5, 8, 9)
plot_id = (1 , 1 , 2, 2, 3)
df = pd.DataFrame(dict(label=label, x=x, y=y, plot_id=plot_id))
这里有一个简单的方法来解决您的问题:
zipped = zip(zip(zip(df.x, df.y), df.plot_id), df.label)
# Result : [(((1, 2), 1), 'A'),
# (((4, 6), 1), 'D'),
# (((9, 5), 2), 'K'),
# (((6, 8), 2), 'L'),
# (((4, 9), 3), 'P')]
要检索位置、绘图索引和标签,您可以按以下方式循环:
for (pos, plot), label in zipped:
...
print pos
print plot
print label
现在您可以根据自己的情况执行以下操作:
import matplotlib.pyplot as plt
for (pos, plot), label in zipped:
plt.figure(plot)
x, y = pos
plt.scatter(x, y)
plt.annotate(label, xy=pos)
它将创建与 plot_ids
一样多的图形,并为每个图形显示具有相应 plot_ids
值的点的散点图。更重要的是,它会在每个点上覆盖标签。