使matplotlib从Python的pandas中的数据框分散绘图

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

例如,如果我有一个数据框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. 例如,如果您现在想要查看col3所有值,以查找在调用中绘制的相应值以scatter ,并按照该值对每个点(或大小)进行着色? 你必须回去,拉出col1,col2的非na值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"]) 
  2. 同样,假设您想根据某些列的值对每个点进行不同的过滤或着色。 例如,如果您想自动绘制在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) 

如何才能做到这一点?

编辑答复船员:

你说最好的方法是分别绘制每个条件(比如subset_asubset_b )。 如果你有很多条件,例如你想把分散点分成4类或更多的点,用不同的形状/颜色来绘制。 你怎么能优雅地适用条件a,b,c等等,并确保你把最后一步“rest”(不在这些条件中的任何一个)作为最后一步?

类似地,在你绘制col1,col2例子中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

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

在这里输入图像说明

与传说的散点图

不过,我发现用图例创build散点图最简单的方法是对每个点types调用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样式设置(例如,颜色/大小)的点。 要find由于NA而跳过的点,请尝试使用isnull方法: df[df.col3.isnull()]

要将点列表分成许多types,请查看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() 

在这里输入图像说明

加勒特的答案很less,但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']) 

将col3中的大小绘制到col1-col2