Pandas在value_counts()中为不存在的类别填充0。

3
问题: 我正在对我的DataFrame结果进行分组,使用value_counts(normalize=True)并尝试在条形图中绘制结果。

问题在于条形图应该包含频率。在某些组中,某些值不会出现。在这种情况下,相应的value_count不是0,而是不存在。对于条形图,这个0值不被考虑在内,导致得到的条形太大了。

示例: 下面是一个最简单的例子,说明了这个问题: 假设DataFrame包含实验的观察结果。当你进行这样一个实验时,一系列的观察结果会被收集起来。实验的结果是收集到的观察结果的相对频率。

df = pd.DataFrame()

df["id"] = [1]*3 + [2]*3 + [3]*3
df["experiment"] = ["a"]*6 + ["b"] * 3
df["observation"] = ["positive"]*3 + ["positive"]*2 + ["negative"]*1 + ["positive"]*2 + ["negative"]*1

dataframe

  • 有两种实验类型,"a"和"b"
  • 属于同一次实验评估的观测结果具有相同的id。

因此,在这里,实验a已经进行了2次,实验b只进行了1次。

我需要按id和实验分组,然后对结果取平均值。

plot_frame = pd.DataFrame(df.groupby(["id", "experiment"])["observation"].value_counts(normalize=True))
plot_frame = plot_frame.rename(columns={"observation":"percentage"})

plot_frame

在上面的图片中,您已经可以看到问题了。评估编号为1的观测结果只包含正面反馈。因此,“负面”出现的相对频率应该是0,但实际上并不存在。如果我绘制这个图表,相应的条形图将会太高,蓝色的条形图应该总和为1:
sns.barplot(data=plot_frame.reset_index(), 
            x="observation", 
            hue="experiment", 
            y="percentage")

plt.show()

barplot

2个回答

4
使用unstack/stack方法并加上参数fill_value=0可以添加填充有0的行。试试这个方法:
df.groupby(["id", "experiment"])["observation"].value_counts(normalize=True).unstack(fill_value=0).stack()

0
我找到了一个巧妙的解决办法,通过迭代索引并手动填充缺失的值:
for a,b,_ in plot_frame.index:
    if (a,b,"negative") not in plot_frame.index:
        plot_frame.loc[(a,b,"negative"), "percentage"] = 0

现在这将产生所需的图表:

barplot

我不特别喜欢这个解决方案,因为它非常针对我的索引,并且如果类别变得更加复杂,可能无法很好地扩展。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接