从 Python 的 pandas 中的数据帧制作 matplotlib 散点图

Posted

技术标签:

【中文标题】从 Python 的 pandas 中的数据帧制作 matplotlib 散点图【英文标题】:making matplotlib scatter plots from dataframes in Python's pandas 【发布时间】:2012-12-27 07:58:27 【问题描述】:

在 Python 中使用 matplotlibpandas 数据帧制作一系列散点图的最佳方法是什么?

例如,如果我有一个数据框 df 有一些感兴趣的列,我发现自己通常会将所有内容都转换为数组:

import matplotlib.pylab as plt
# df is a DataFrame: fetch col1 and col2 
# and drop na rows if any of the columns are NA
mydata = df[["col1", "col2"]].dropna(how="any")
# Now plot with matplotlib
vals = mydata.values
plt.scatter(vals[:, 0], vals[:, 1])

在绘图之前将所有内容都转换为数组的问题在于它会迫使您跳出数据框。

考虑这两个用例,其中拥有完整的数据框对于绘图至关重要:

    例如,如果您现在想查看 col3 的所有值以查找您在调用 scatter 时绘制的相应值,并根据该值对每个点(或大小)进行着色?您必须返回,取出 col1,col2 的非 na 值并检查它们对应的值。

    有没有办法在保留数据框的同时进行绘图?例如:

    mydata = df.dropna(how="any", subset=["col1", "col2"])
    # plot a scatter of col1 by col2, with sizes according to col3
    scatter(mydata(["col1", "col2"]), s=mydata["col3"])
    

    同样,假设您想根据某些列的值对每个点进行不同的过滤或着色。例如。如果你想自动绘制在col1, col2 上满足某个截止点的点的标签(标签存储在 df 的另一列中),或者对这些点进行不同的着色,就像人们对 R 中的数据框所做的那样.例如:

    mydata = df.dropna(how="any", subset=["col1", "col2"]) 
    myscatter = scatter(mydata[["col1", "col2"]], s=1)
    # Plot in red, with smaller size, all the points that 
    # have a col2 value greater than 0.5
    myscatter.replot(mydata["col2"] > 0.5, color="red", s=0.5)
    

如何做到这一点?

编辑回复crewbum:

您说最好的方法是分别绘制每个条件(如subset_asubset_b)。如果你有很多条件怎么办,例如您想将散点分成 4 种类型甚至更多,以不同的形状/颜色绘制每个点。您如何优雅地应用条件 a、b、c 等,并确保在最后一步绘制“其余”(不在任何这些条件下的事物)?

类似地,在您的示例中,您根据 col3 以不同方式绘制 col1,col2,如果有 NA 值破坏了 col1,col2,col3 之间的关联怎么办?例如,如果您想根据col3 值绘制所有col2 值,但某些行在col1col3 中具有NA 值,则迫使您首先使用dropna。所以你会这样做:

mydata = df.dropna(how="any", subset=["col1", "col2", "col3")

然后你可以像你展示的那样使用mydata 绘制——使用col3 的值绘制col1,col2 之间的散点图。但是mydata 将丢失一些具有col1,col2 值但对于col3 不适用的点,并且这些点仍然需要绘制......那么你将如何基本上绘制数据的“其余部分”,即过滤集mydata的点?

【问题讨论】:

在此期间情况有所变化,请参阅官方文档中的Plotting - Plotting - Scatter plot。 【参考方案1】:

尝试将 DataFrame 的列直接传递给 matplotlib,如下例所示,而不是将它们提取为 numpy 数组。

df = pd.DataFrame(np.random.randn(10,2), columns=['col1','col2'])
df['col3'] = np.arange(len(df))**2 * 100 + 100

In [5]: df
Out[5]: 
       col1      col2  col3
0 -1.000075 -0.759910   100
1  0.510382  0.972615   200
2  1.872067 -0.731010   500
3  0.131612  1.075142  1000
4  1.497820  0.237024  1700

根据另一列改变散点大小

plt.scatter(df.col1, df.col2, s=df.col3)
# OR (with pandas 0.13 and up)
df.plot(kind='scatter', x='col1', y='col2', s=df.col3)

根据另一列改变散点颜色

colors = np.where(df.col3 > 300, 'r', 'k')
plt.scatter(df.col1, df.col2, s=120, c=colors)
# OR (with pandas 0.13 and up)
df.plot(kind='scatter', x='col1', y='col2', s=120, c=colors)

带有图例的散点图

但是,我发现创建带有图例的散点图的最简单方法是为每种点类型调用一次 plt.scatter

cond = df.col3 > 300
subset_a = df[cond].dropna()
subset_b = df[~cond].dropna()
plt.scatter(subset_a.col1, subset_a.col2, s=120, c='b', label='col3 > 300')
plt.scatter(subset_b.col1, subset_b.col2, s=60, c='r', label='col3 <= 300') 
plt.legend()

更新

据我所知,matplotlib 只是跳过具有 NA x/y 坐标或 NA 样式设置(例如颜色/大小)的点。要查找因 NA 而跳过的点,请尝试 isnull 方法:df[df.col3.isnull()]

要将点列表拆分为多种类型,请查看numpy select,它是一个向量化的 if-then-else 实现并接受可选的默认值。例如:

df['subset'] = np.select([df.col3 < 150, df.col3 < 400, df.col3 < 600],
                         [0, 1, 2], -1)
for color, label in zip('bgrm', [0, 1, 2, -1]):
    subset = df[df.subset == label]
    plt.scatter(subset.col1, subset.col2, s=120, c=color, label=str(label))
plt.legend()

【讨论】:

很好的答案!我不知道这些。我通常将我的数据转换成我喜欢的格式并将其发送到 R 以获取 ggplot。这些示例将让我在 pandas/python 中做更多事情 - 谢谢。 如何在图例中制作具有特定大小的单个圆圈?【参考方案2】:

加勒特的出色答案几乎没有什么可补充的,但熊猫也有一个scatter method。使用它,就这么简单

df = pd.DataFrame(np.random.randn(10,2), columns=['col1','col2'])
df['col3'] = np.arange(len(df))**2 * 100 + 100
df.plot.scatter('col1', 'col2', df['col3'])

【讨论】:

【参考方案3】:

我会推荐使用另一种方法,使用seaborn,这是一种更强大的数据绘图工具。您可以使用seaborn scatterplot 并将列3 定义为huesize

工作代码:

import pandas as pd
import seaborn as sns
import numpy as np

#creating sample data 
sample_data='col_name_1':np.random.rand(20),
      'col_name_2': np.random.rand(20),'col_name_3': np.arange(20)*100
df= pd.DataFrame(sample_data)
sns.scatterplot(x="col_name_1", y="col_name_2", data=df, hue="col_name_3",size="col_name_3")

【讨论】:

以上是关于从 Python 的 pandas 中的数据帧制作 matplotlib 散点图的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas:合并两个没有键的表(将 2 个数据帧与广播所有元素相乘;NxN 数据帧)

基于另一个数据帧 Python 和 Pandas 从数据帧中采样

PYTHON Pandas - 根据其他数据帧中的值对数据帧使用 Pandas 样式

高效地将大型 Pandas 数据帧读取到磁盘

Python Pandas从现有数据帧的所有行组合创建新的数据帧

行中的 Python/Pandas 数据帧时间数据(按名称分组)