Python Pandas 绘制堆叠数据子图
我想要制作一些图表(或者子图),这些图表是基于一个pandas数据框中的分组数据。我觉得这应该是个基础的操作,但我好像漏掉了什么。我有一些输入数据,这些数据是以“堆叠”的形式准备的,下面有个例子。我想为每个上层数据(upperLevel)制作一个像下面这样的图表:
这里有一些示例数据(我把我使用的示例.csv数据粘贴在下面)。这些数据是以“堆叠”的形式呈现的,包含数据类型、时间和数据。数据类型描述了某个数据点的类别和子类别。
import pandas as pd
import re
import matplotlib.pyplot as plt
df=pd.read_csv('.....TestData.csv',index_col='T')
df=df.stack(0).reset_index(1)
df.columns=['fullType','data']
#And at this point, this is pretty much the form of my actual data
#So I split it up a bit to try to get columns for different data groupings
regexStr='~'
def upperParser(row):
label=re.split(regexStr,row['fullType'])
return label[1]
def lowerParser(row):
label=re.split(regexStr,row['fullType'])
return label[2]
df['upperLevel']=df.apply(upperParser,axis=1)
df['lowerLevel']=df.apply(lowerParser,axis=1)
df['time']=df.index
df=df.reset_index(drop=True)
plt.figure();
df.plot();
#And here is one of many attempts... I just seem to be missing something that should be simple:
for grp in df.groupby('upperLevel'):
for key,grp in df.groupby('lowerLevel'):
plt.plot(x='time',y=grp['data'],label=key)
plt.show()
任何建议都非常感谢。我并不在意保持某种特定的格式。我的最终目标是绘制所有上层类别的图表(比如A=(0,1),B=(0,2)),并使用mpl3d来查看底层的子图(就像这个,但每个子类别1,2,3作为子图堆叠)。不过我想先从基础开始。
示例数据:
T Col~A~1~ Col~A~2~ Col~A~3~ Col~B~1~ Col~B~2~ Col~B~3~
1 1 0.5 0.5 0.5 0.25 0.25
1.5 2 1 1 1 0.5 0.5
2 3 1.5 0.5 1.5 0.75 0.25
2.5 4 2 1 2 1 0.5
3 5 2.5 0.5 2.5 1.25 0.25
3.5 6 3 1 3 1.5 0.5
4 7 3.5 0.5 3.5 1.75 0.25
4.5 8 4 1 4 2 0.5
5 9 4.5 0.5 4.5 2.25 0.25
5.5 10 5 1 5 2.5 0.5
6 11 5.5 0.5 5.5 2.75 0.25
6.5 12 6 1 6 3 0.5
7 13 6.5 0.5 6.5 3.25 0.25
7.5 14 7 1 7 3.5 0.5
8 15 7.5 0.5 7.5 3.75 0.25
8.5 16 8 1 8 4 0.5
9 17 8.5 0.5 8.5 4.25 0.25
9.5 18 9 1 9 4.5 0.5
10 19 9.5 0.5 9.5 4.75 0.25
2 个回答
1
我同意,这确实是个很有用的功能。我希望Pandas能有一个更高级的子图功能,能够按行分组和按列分组来创建子图。
这里有一个可以实现这个功能的函数,你可以试试看:
def subplotter(df):
numcols = list(df.select_dtypes(include=['number']).columns)
objcols = list(df.select_dtypes(include=['object']).columns)
grouped = df.groupby(objcols)
l = len(grouped.groups)
cols = dict({1:1,2:1,3:1,4:2,5:2,6:2}, **{e:3 for e in range(7,25,1)})[l]
rows = np.ceil(l/(cols*1.0))
i, fig = 1, plt.figure(figsize=(5*cols,4*rows))
for name, group in grouped:
ax = fig.add_subplot(rows, cols, i)
plt.plot(group[numcols])
plt.legend(numcols)
plt.title(', '.join([': '.join(e) for e in zip(objcols, name)]))
plt.legend(numcols)
i += 1
plt.tight_layout()
return
这个函数会根据所有的对象类型列来对数据框进行分组,并为每个组创建子图。所有数字类型的列都会放在每个子图中。
我增加的复杂性主要是为了确定图形的合适大小、子图的位置(行和列),以及添加图例和标题。
2
这里有几个小建议:
df.groupby()
会返回一个包含(组名, 组)
的元组,所以在遍历这些组的时候要注意这一点。- 如果你想要的图表已经可以通过
pandas
的绘图方法实现,通常就不需要手动使用pyplot
了。 pandas
的绘图方法通常会为数据框中的每一列生成一条单独的线,所以如果你能把数据整理成不同的列,就能轻松得到你想要的图表。pandas
的绘图方法默认会使用数据框的索引作为 x 轴。
也就是说,你可以用以下代码生成你想要的图表:
for group_name, grp in df.groupby('upperLevel'):
plot_table = grp.pivot(index='time', columns='lowerLevel', values='data')
plot_table.plot()