使用groupby和pandas datafram中的多个列从字符串数据创建条形图

2024-09-27 18:03:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我想用python绘制一个条形图,其中包含来自“yes”或“no”的数据计数的多个x-categories。我已经开始编写一些代码,但我相信我正在以一种缓慢的方式找到我想要的解决方案。我很乐意使用seaborn、Matplotlib或pandas的解决方案,但我不想使用Bokeh,因为我希望能制作出符合出版质量的数字。在

最终我想要的是:

  • 在x轴上用“独木舟”、“巡航”、“皮划艇”和“船”等类别绘制条形图
  • 按“颜色”分组,所以不是绿色就是红色
  • 显示“是”响应的比例:所以“是”行的数量除以“红色”和“绿色”的计数,在本例中是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)

这是我的开始:

^{pr2}$

enter image description here

但我真正想要的是,所有的x类都在一个图上,只显示“是”回答的结果,并将其作为“是”的比例,而不仅仅是计数。帮忙吗?在


Tags: 数据no绘制greenredyescolor计数
3条回答

不太确定我是否正确地理解了这个问题。看看每种船型和颜色的答案比例似乎更有意义。在

import matplotlib.pyplot as plt
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)

ax = df.replace(["Yes","No"],[1,0]).groupby("color").mean().transpose().plot.bar(color=["g","r"])
ax.set_title('Proportion "Yes" answers per of boat type and color')
plt.show()

enter image description here

这意味着25%的绿色独木舟回答“是”。在

我们试试吧。在

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)

输出:

enter image description here

不确定你到底是不是在找它,让我知道它是否有效。在

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

tidy_df = pd.melt(df, id_vars=['color'] ,var_name='variable', value_name='value')
total_df = tidy_df[['variable']].groupby('variable').size().reset_index()
tidy_df = tidy_df.groupby(['color', 'variable', 'value']).size().reset_index()

merged_df = pd.merge(tidy_df, total_df, on='variable', how='left', suffixes=('_left', '_right'))
merged_df['proportion'] = merged_df['0_left']/merged_df['0_right']

# merged_df[merged_df['value'] == 'Yes']

palette ={"Green":"green","Red":"red"} # optional you can select your own
plt.figure(figsize=(12, 6))
sns.barplot(x='variable', y='proportion', hue='color',data=merged_df[merged_df['value'] == 'Yes'], palette=palette)
plt.xticks(rotation=65)
#plt.savefig('numbers.png')
plt.show()

enter image description here

相关问题 更多 >

    热门问题