【问题标题】:How can I plot a pandas multiindex dataframe as 3d如何将 pandas 多索引数据框绘制为 3d
【发布时间】:2016-12-31 17:07:45
【问题描述】:

我有一个数据框 df 分组如下:

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

我想在matplotlib 中将其绘制为 3d 图表,其中Year 作为 x 轴,Sales 在 y 轴上,Product 在 z 轴上。

我一直在尝试以下方法:

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: 尺寸不兼容: 参数 'height' 的长度必须为 7 或 标量"

【问题讨论】:

    标签: python pandas matplotlib 3d seaborn


    【解决方案1】:

    您可以使用Pandas 绘制一个 3D 条形图,如图所示:

    设置:

    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) 进行分组并遍历它们,然后将它们附加到 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()
    


    注意:

    如果groupby 对象不平衡,您仍然可以通过unstacking 进行处理 并用 0 填充 Nans,然后将 stacking 填充如下:

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

    df_multi_index.unstack 是您的原始多索引数据框。

    对于添加到多索引数据框的新值,得到以下图表:

    【讨论】:

    • 感谢 Nickil Maveli,这似乎让我更接近解决方案。我已经编辑了这个问题,以更好地展示我想要实现的目标。在您的回答中,条形图是平的,并且它们没有显示在每个产品的位置上?我总是必须做 reset_index 来做情节吗?
    • 我希望我的编辑回复确实是您想要的样子。我保持 Multi-Index 数据框对象不变,因此您可以在不使用 reset_index 将其转换为 dataframe 对象的情况下绘制它。
    • 太棒了!谢谢你。我想我仍然需要稍微消化一下代码:-)唯一的事情是,如果我向数据框添加另一个值,它就不再起作用了,例如'2012' 'A' '105' 然后我收到错误'ValueError:操作数无法与形状一起广播(42,1)(54,4)'你知道我必须在哪里更改代码吗?
    • 是的。这些是我早期方法的缺点。我已经纠正了它并显示了你提到的新值的图。
    • 非常感谢。这是一个很好的解决方案!
    猜你喜欢
    • 2018-10-29
    • 1970-01-01
    • 2021-10-08
    • 2020-10-22
    • 2020-07-11
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多