代码之家  ›  专栏  ›  技术社区  ›  Fourier

从多个类别中创建分组/堆叠条形图,这些类别包含pandas数据框中的多个标签

  •  0
  • Fourier  · 技术社区  · 8 年前

    我有以下几点 pandas 数据帧( df )[ 仅摘录完整数据帧 ]:

       Name    Cat_1    Cat_2
    0   foo        P    Apples, Pears, Cats
    1   bar     R, M    Apples
    2   bla        E    Pears
    3   blu        F    Cats, Pears
    4   boo        G    Apples, Pears
    5   faa     P, E    Apples, Cats
    

    我想创建条形图,这些条形图是根据 Cat_1 Cat_2 。 这些列包含多个标记,这些标记必须用于打印。

    目前,我正在运行这个简单的代码来绘制 Cat\U 1 :

    import pandas as pd
    from matplotlib import pyplot as plt
    
    fig, ax = plt.subplots(figsize = (4,4))
    s = df["Cat_1"].str.split(", ", expand = True).stack()
    s.value_counts().plot(kind = 'bar', ax = ax)
    

    这将为中的每个不同标签返回一个很好的条形图 Cat\U 1 允许多个工作分配(如预期)。

    可以将相同的应用于 Cat\U 2 并获得带有相应标签的单独绘图。

    但是,我希望有一个单独的绘图,它首先是由 Cat\U 1 然后计算值 Cat\U 2

    我想一种方法是构建一个嵌套字典,如下所示:

    {"P": {"Apples": 2, "Pears": 1, "Cats": 2}, "R": {"Apples": 1}, ....}
    

    但同时要跟踪 Cat\U 1

    不管最后是分组条形图还是堆叠条形图。

    请查看附图,了解更直观的想法:

    enter image description here

    1 回复  |  直到 8 年前
        1
  •  1
  •   ak_slick    8 年前

    如果我理解正确的话,这应该会让你非常接近。

    import numpy as np
    import matplotlib.pyplot as plt
    import pandas as pd
    
    df = pd.DataFrame(columns=['Name', 'Cat_1', 'Cat_2'])
    
    df['Name'] = ['foo', 'bar', 'bla', 'blu', 'boo', 'faa']
    df['Cat_1'] = ['P', 'R, M', 'E', 'F', 'G', 'P, E']
    df['Cat_2'] = ['Apples, Pears, Cats', 'Apples', 'Pears', 'Cats, Pears', 'Apples, Pears', 'Apples, Cats']
    
    # arrange data simply prepopulate with zero
    df_pl = pd.DataFrame(columns=df["Cat_1"].str.split(", ", expand=True).stack().unique().tolist(),
                         index=df["Cat_2"].str.split(", ", expand=True).stack().unique().tolist(),
                         data=0)
    
    # get chunk size for each combination
    for x in df_pl.columns:
        ind = df.Cat_1.str.contains(x)
        for name in df_pl.index:
            df_pl.set_value(name, x, df.loc[ind, 'Cat_2'].str.contains(name).sum())
    
    N = len(df_pl.columns)
    ind = np.arange(N)    # the x locations for the groups
    width = 0.35       # the width of the bars: can also be len(x) sequence
    
    plotted = []
    p = {}
    for name in df_pl.index:
        bottoms = df_pl.index.isin(plotted).sum()
        p[name] = plt.bar(ind, df_pl.loc[name].values.tolist(), bottom=bottoms)
        plotted.append(name)
    
    plt.ylabel('y_label')
    plt.title('some plot')
    plt.xticks(ind, df_pl.columns.tolist())
    plt.legend(p.values(), p.keys())
    
    plt.show()
    

    Example Output