2016-08-24 131 views
3

我有分组这样的数据帧df我如何绘制大熊猫多指标数据帧的3D

Year Product Sales 
2010  A 111 
      B 20 
      C 150 
2011  A 10 
      B 28 
      C 190 
      … … 

,我想在matplotlib绘制此为具有Year为x轴的三维图,在y轴上为Sales,在z轴上为Productenter image description here

我一直在尝试以下操作:

from mpl_toolkits.mplot3d import axes3d 
fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
X = dfgrouped['Year'] 
Y = dfgrouped['Sales'] 
Z = dfgrouped['Product'] 
ax.bar(X, Y, Z, color=cs, alpha=0.8) 

不幸的是我得到

"ValueError: incompatible sizes: argument 'height' must be length 7 or scalar"

回答

4

你可以绘制如图使用Pandas三维条形图:

设置:

arrays = [[2010, 2010, 2010, 2011, 2011, 2011],['A', 'B', 'C', 'A', 'B', 'C']] 
tuples = list(zip(*arrays)) 
index = pd.MultiIndex.from_tuples(tuples, names=['Year', 'Product'])   

df = pd.DataFrame({'Sales': [111, 20, 150, 10, 28, 190]}, index=index) 
print (df) 

       Sales 
Year Product  
2010 A   111 
    B   20 
    C   150 
2011 A   10 
    B   28 
    C   190 

数据角力:

import numpy as np 
import pandas as pd 
from mpl_toolkits.mplot3d import axes3d 
import matplotlib.pyplot as plt 

# Set plotting style 
plt.style.use('seaborn-white') 

分组类似条目(get_group)存在的Sales列并通过它们迭代后来它们附加到一个list。这使用np.hstack水平堆叠,形成3d图的z尺寸。

L = [] 
for i, group in df.groupby(level=1)['Sales']: 
    L.append(group.values) 
z = np.hstack(L).ravel() 

让x和y两个维上的标签采用多索引数据帧各个级别的唯一值。 x和y维度取这些值的范围。

xlabels = df.index.get_level_values('Year').unique() 
ylabels = df.index.get_level_values('Product').unique() 
x = np.arange(xlabels.shape[0]) 
y = np.arange(ylabels.shape[0]) 

返回坐标从坐标向量矩阵使用np.meshgrid

x_M, y_M = np.meshgrid(x, y, copy=False) 

3-d绘图:

fig = plt.figure(figsize=(10, 10)) 
ax = fig.add_subplot(111, projection='3d') 

# Making the intervals in the axes match with their respective entries 
ax.w_xaxis.set_ticks(x + 0.5/2.) 
ax.w_yaxis.set_ticks(y + 0.5/2.) 

# Renaming the ticks as they were before 
ax.w_xaxis.set_ticklabels(xlabels) 
ax.w_yaxis.set_ticklabels(ylabels) 

# Labeling the 3 dimensions 
ax.set_xlabel('Year') 
ax.set_ylabel('Product') 
ax.set_zlabel('Sales') 

# Choosing the range of values to be extended in the set colormap 
values = np.linspace(0.2, 1., x_M.ravel().shape[0]) 

# Selecting an appropriate colormap 
colors = plt.cm.Spectral(values) 
ax.bar3d(x_M.ravel(), y_M.ravel(), z*0, dx=0.5, dy=0.5, dz=z, color=colors) 
plt.show() 

Image


注:

不平衡groupby对象的柜面,你仍然可以通过unstacking 做到这一点,填补Nans用0,然后stacking回如下:

df = df_multi_index.unstack().fillna(0).stack() 

其中df_multi_index.unstack是你原来的多 - 索引数据帧。

对于加入到多指标数据帧的新值,得到以下情节:

Image2

+0

感谢Nickil Maveli,这似乎让我有点接近的解决方案。我已经编辑了这个问题,以更好地展示我想达到的目标。在你的答案中,酒吧是平的,他们没有显示在每个产品的位置?我是否总是必须执行reset_index才能完成剧情? –

+0

我希望我编辑的回复*的确是你想要的样子。我保持'Multi-Index'数据框对象不变,因此您可以绘制它,而不必使用'reset_index'将其转换为'dataframe'对象。 –

+0

真棒它的作品!谢谢。我认为我仍然需要稍微消化代码,但是:-)唯一的问题是,如果我在数据框中添加另一个值,它就可以继续工作了,例如, '2012''A''105',那么我得到错误'ValueError:操作数不能与形状一起广播(42,1)(54,4)'你知道我必须改变代码吗? –