使用Python的pandas从数据框绘制matplotlib散点图

91

使用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])

将所有内容转换为数组后进行绘图的问题在于,它会强制你跳出数据框架。

考虑以下两种情况,在这些情况下,完整的数据框架对于绘图至关重要:

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

    有没有一种方法可以在保持数据框架的同时进行绘图呢?例如:

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 上某个截止值的点的标签(标签存储在数据框的另一列中),或者像 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等并确保然后将“其余部分”(不属于这些条件中任何一个的事物)作为最后一步绘制?

在您绘制 col1,col2 不同于基于 col3 的示例中,如果存在破坏 col1,col2,col3 之间关联的 NA 值怎么办?例如,如果您想根据它们的 col3 值绘制所有 col2 值,但某些行在 col1col3 中具有 NA 值,则强制您首先使用 dropna。因此,您需要执行以下操作:

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

那么你可以使用 mydata 进行绘图,就像你展示的一样 - 使用 col3 的值绘制 col1,col2 之间的散点。但是,mydata 将缺少某些具有 col1,col2 值但对于 col3 是 NA 的点,并且这些点仍然需要绘制... 那么你如何基本绘制“剩余”的数据,即不在过滤集合mydata中的点?


2
事情在此期间发生了变化,请参阅官方文档中的绘图-散点图 - Piotr Migdal
3个回答

122
尝试直接将 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)

enter image description here

基于另一列变化散点颜色
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)

enter image description here

带图例的散点图

然而,我发现创建带有图例的散点图最简单的方法是为每种点类型调用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()

enter image description here

更新

据我所知,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()

enter image description here


1
太棒了!我之前不知道这些。通常我会将数据转换成我需要的格式,然后将其发送到R中进行ggplot绘图。这些示例将让我在pandas / python中做更多的事情 - 谢谢。 - zach
如何在图例中制作特定大小的单个圆? - nbsrujan

8

Garrett 的回答已经详尽了,但是 pandas 也有一个散点图方法 scatter。使用它就像这样简单:

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'])

plotting sizes in col3 to col1-col2


5

我建议使用一种替代方法,使用更强大的数据绘图工具——seaborn。您可以使用seaborn scatterplot,并将第三列定义为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")

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接