使用Python中matplotlib
数据框的pandas
制作一系列散点图的最佳方法是什么?
例如,如果我的数据框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)
如何做到这一点?
编辑回复船员:
你说最好的方法是分别绘制每个条件(如subset_a
,subset_b
)。如果您有很多条件,例如您希望将散点图分成4种类型的点甚至更多,以不同的形状/颜色绘制每种点。你如何优雅地应用条件a,b,c等,并确保你然后将“其余”(不是在任何这些条件下的东西)作为最后一步?
同样在您根据col1,col2
以不同方式绘制col3
的示例中,如果有NA值会破坏col1,col2,col3
之间的关联怎么办?例如,如果您要根据col2
值绘制所有col3
值,但某些行在col1
或col3
中具有NA值,则强制您使用{ {1}}首先。所以你会这样做:
dropna
然后您可以使用mydata = df.dropna(how="any", subset=["col1", "col2", "col3")
进行情节绘制 - 使用mydata
的值绘制col1,col2
之间的散点图。但是col3
会丢失一些具有mydata
值但是col1,col2
的NA的点,而那些仍需要绘制...那么你将如何绘制“其余”数据,即过滤集col3
中不的点?
答案 0 :(得分:94)
尝试将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()
答案 1 :(得分:4)
加勒特的答案很少,但熊猫也有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'])
答案 2 :(得分:0)
我将建议使用另一种使用seaborn
的方法,该方法是功能更强大的数据绘图工具。您可以使用seaborn scatterplot
并将第3列定义为hue
和size
。
工作代码:
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")