我想在python中用多个x类别从"is"或“否”的数据中绘制条形图。我已经开始编写一些代码,但是我认为我正在以缓慢的方式获得所需的解决方案。对于使用seaborn,Matplotlib或pandas但不使用Bokeh的解决方案,我会很好,因为我想制作可缩放的出版物质量的数字。

最终我想要的是:

  • 条形图,在x轴上带有类别“canoe”,“cruise”,“kayak”和“ship”
  • 按“颜色”分组,因此绿色或红色
  • 显示"is"响应的比例:是行数除以“红色”和“绿色”的计数,在这种情况下为4红色和4绿色,但是可以改变。

  • 这是我正在使用的数据集:
    import pandas as pd
    data = [{'ship': 'Yes','canoe': 'Yes', 'cruise': 'Yes', 'kayak': 'No','color': 'Red'},{'ship': 'Yes', 'cruise': 'Yes', 'kayak': 'Yes','canoe': 'No','color': 'Green'},{'ship': 'Yes', 'cruise': 'Yes', 'kayak': 'No','canoe': 'No','color': 'Green'},{'ship': 'Yes', 'cruise': 'Yes', 'kayak': 'No','canoe': 'No','color': 'Red'},{'ship': 'Yes', 'cruise': 'Yes', 'kayak': 'Yes','canoe': 'No','color': 'Red'},{'ship': 'No', 'cruise': 'Yes', 'kayak': 'No','canoe': 'Yes','color': 'Green'},{'ship': 'No', 'cruise': 'No', 'kayak': 'No','canoe': 'No','color': 'Green'},{'ship': 'No', 'cruise': 'No', 'kayak': 'No','canoe': 'No','color': 'Red'}]
    df = pd.DataFrame(data)
    

    这就是我开始的目的:
    print(df['color'].value_counts())
    
    red = 4 # there must be a better way to code this rather than manually. Perhaps using len()?
    green = 4
    
    # get count per type
    ca = df['canoe'].value_counts()
    cr = df['cruise'].value_counts()
    ka = df['kayak'].value_counts()
    sh = df['ship'].value_counts()
    print(ca, cr, ka, sh)
    
    # group by color
    cac = df.groupby(['canoe','color'])
    crc = df.groupby(['cruise','color'])
    kac = df.groupby(['kayak','color'])
    shc = df.groupby(['ship','color'])
    
    # make plots
    cac2 = cac['color'].value_counts().unstack()
    cac2.plot(kind='bar', title = 'Canoe by color')
    

    python - 使用groupby和pandas数据框中的多列从字符串数据创建条形图-LMLPHP

    但是,我真正想要的是所有x类别都放在一个图上,只显示"is"响应的结果,并视为"is"的比例,而不是仅仅计算在内。帮助?

    最佳答案

    我们试试看。

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from itertools import groupby
    
    data = [{'ship': 'Yes','canoe': 'Yes', 'cruise': 'Yes', 'kayak': 'No','color': 'Red'},{'ship': 'Yes', 'cruise': 'Yes', 'kayak': 'Yes','canoe': 'No','color': 'Green'},{'ship': 'Yes', 'cruise': 'Yes', 'kayak': 'No','canoe': 'No','color': 'Green'},{'ship': 'Yes', 'cruise': 'Yes', 'kayak': 'No','canoe': 'No','color': 'Red'},{'ship': 'Yes', 'cruise': 'Yes', 'kayak': 'Yes','canoe': 'No','color': 'Red'},{'ship': 'No', 'cruise': 'Yes', 'kayak': 'No','canoe': 'Yes','color': 'Green'},{'ship': 'No', 'cruise': 'No', 'kayak': 'No','canoe': 'No','color': 'Green'},{'ship': 'No', 'cruise': 'No', 'kayak': 'No','canoe': 'No','color': 'Red'}]
    df = pd.DataFrame(data)
    df1 = df.replace(["Yes","No"],[1,0]).groupby("color").mean().stack().rename('% Yes').to_frame()
    
    
    def add_line(ax, xpos, ypos):
        line = plt.Line2D([xpos, xpos], [ypos + .1, ypos],
                          transform=ax.transAxes, color='gray')
        line.set_clip_on(False)
        ax.add_line(line)
    
    def label_len(my_index,level):
        labels = my_index.get_level_values(level)
        return [(k, sum(1 for i in g)) for k,g in groupby(labels)]
    
    def label_group_bar_table(ax, df):
        ypos = -.1
        scale = 1./df.index.size
        for level in range(df.index.nlevels)[::-1]:
            pos = 0
            for label, rpos in label_len(df.index,level):
                lxpos = (pos + .5 * rpos)*scale
                ax.text(lxpos, ypos, label, ha='center', transform=ax.transAxes)
                add_line(ax, pos*scale, ypos)
                pos += rpos
            add_line(ax, pos*scale , ypos)
            ypos -= .1
    
    
    colorlist = ['green','red']
    cp = sns.color_palette(colorlist)
    
    ax = sns.barplot(x=df1.index, y='% Yes', hue = df1.index.get_level_values(0), data=df1, palette=cp)
    #Below 2 lines remove default labels
    ax.set_xticklabels('')
    ax.set_xlabel('')
    label_group_bar_table(ax, df1)
    

    输出:

    python - 使用groupby和pandas数据框中的多列从字符串数据创建条形图-LMLPHP

    关于python - 使用groupby和pandas数据框中的多列从字符串数据创建条形图,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51532581/

    10-12 16:35
    查看更多