47

我想用图上点旁边的值来注释数据点。我发现的示例仅将 x 和 y 作为向量处理。但是,我想为包含多列的 pandas DataFrame 执行此操作。

ax = plt.figure().add_subplot(1, 1, 1)
df.plot(ax = ax)
plt.show()

注释多列 DataFrame 的所有点的最佳方法是什么?

4

4 回答 4

54

这是Dan Allan 的回答的(非常)稍微简洁的版本:

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import string

df = pd.DataFrame({'x':np.random.rand(10), 'y':np.random.rand(10)}, 
                  index=list(string.ascii_lowercase[:10]))

这使:

          x         y
a  0.541974  0.042185
b  0.036188  0.775425
c  0.950099  0.888305
d  0.739367  0.638368
e  0.739910  0.596037
f  0.974529  0.111819
g  0.640637  0.161805
h  0.554600  0.172221
i  0.718941  0.192932
j  0.447242  0.172469

进而:

fig, ax = plt.subplots()
df.plot('x', 'y', kind='scatter', ax=ax)

for k, v in df.iterrows():
    ax.annotate(k, v)

最后,如果您处于交互模式,您可能需要刷新绘图:

fig.canvas.draw()

产生: 无聊的散点图

或者,因为这看起来非常难看,你可以很容易地美化一些东西:

from matplotlib import cm
cmap = cm.get_cmap('Spectral')
df.plot('x', 'y', kind='scatter', ax=ax, s=120, linewidth=0, 
        c=range(len(df)), colormap=cmap)

for k, v in df.iterrows():
    ax.annotate(k, v,
                xytext=(10,-5), textcoords='offset points',
                family='sans-serif', fontsize=18, color='darkslategrey')

哪个看起来好多了: 漂亮的散点图

于 2014-09-23T16:50:16.560 回答
40

您想使用其他列之一作为注释的文本吗?这是我最近做的事情。

从一些示例数据开始

In [1]: df
Out[1]: 
           x         y val
 0 -1.015235  0.840049   a
 1 -0.427016  0.880745   b
 2  0.744470 -0.401485   c
 3  1.334952 -0.708141   d
 4  0.127634 -1.335107   e

绘制点。在这个例子中,我将 y 与 x 作图。

ax = df.set_index('x')['y'].plot(style='o')

编写一个循环遍历 x、y 和要在该点旁边注释的值的函数。

def label_point(x, y, val, ax):
    a = pd.concat({'x': x, 'y': y, 'val': val}, axis=1)
    for i, point in a.iterrows():
        ax.text(point['x'], point['y'], str(point['val']))

label_point(df.x, df.y, df.val, ax)

draw()

注释点

于 2013-04-09T19:59:43.870 回答
31

假设您df有多个列,其中三个是xylbl。要使用 注释(x,y)散点图lbl,只需:

ax = df.plot(kind='scatter',x='x',y='y')
df[['x','y','lbl']].apply(lambda row: ax.text(*row),axis=1);
于 2016-09-07T16:05:20.790 回答
12

我发现以前的答案很有帮助,尤其是LondonRob 的示例,它稍微改进了布局。

唯一困扰我的是我不喜欢从 DataFrames 中提取数据然后循环它们。似乎浪费了DataFrame。

这是使用 .apply() 避免循环的替代方法,并包含更好看的注释(我认为色阶有点过分,无法让颜色条消失):

ax = df.plot('x', 'y', kind='scatter', s=50 )

def annotate_df(row):  
    ax.annotate(row.name, row.values,
                xytext=(10,-5), 
                textcoords='offset points',
                size=18, 
                color='darkslategrey')
    
_ = df.apply(annotate_df, axis=1)

在此处输入图像描述

编辑笔记

我最近编辑了我的代码示例。最初它使用相同的:

fig, ax = plt.subplots()

作为暴露轴的其他帖子,但是这是不必要的,并且使:

import matplotlib.pyplot as plt

线也不必要。

另请注意:

  • 如果您尝试重现此示例,并且您的绘图中的点与我们的任何位置都不相同,则可能是因为 DataFrame 使用了随机值。如果我们使用固定数据表或随机种子,它可能不会那么混乱。
  • 根据分数的不同,您可能必须使用这些xytext值来获得更好的展示位置。
于 2015-01-04T00:30:52.270 回答