如果不存在,Pandas groupby 0值

时间:2018-04-28 16:11:17

标签: python pandas pandas-groupby

我有这样的代码

frame[frame['value_text'].str.match('Type 2')  | frame['value_text'].str.match('Type II diabetes')].groupby(['value_text','gender'])['value_text'].count()

返回类似

的系列
value_text            gender      count
type 2                  M           4
type 2 without...       M           4
                        F           3

我想要的是

 value_text               gender      count
    type 2                  M           4
                            F           0
    type 2 without...       M           4
                            F           3

我希望包括所有性别的计数,即使数据框中没有记录。我怎么能这样做?

4 个答案:

答案 0 :(得分:1)

请记住,每当您想强制使用特定列表来索引/整形数据时。 Pivot 交叉表堆栈 unstack 不可靠,因为它们高度依赖于输入数据。例如,如果“M”从未显示在任何输入行中,则无论您如何转动/取消堆叠结果,都不会看到“M”。这种问题是 reindex()闪耀的地方。

假设您预先处理的相框保存为 df

  mdx1 = pd.MultiIndex.from_product([df.index.levels[0], ['M', 'F']])
  df.reindex(mdx1).fillna(0, downcast='infer')

另一方面,如果您只想在所有级别0中显示所有可能的级别1值,请执行以下操作:

  mdx1 = pd.MultiIndex.from_product(df.index.levels)
  df.reindex(mdx1).fillna(0, downcast='infer')

这可以很容易地扩展到具有2级以上索引的数据帧。

更新:使用分类数据类型可能会修复类似枢轴的函数所具有的问题。

答案 1 :(得分:1)

Categorical Data已在pandas中专门用于此目的。

实际上,使用分类数据的groupby操作会自动计算笛卡尔积。

与其他功能方法相比,您应该会看到更多优势:更低的内存使用率和数据验证。

import pandas as pd

df = pd.DataFrame({'value_text': ['type2', 'type2 without', 'type2'],
                   'gender': ['M', 'F', 'M'],
                   'value': [1, 2, 3]})

df['gender'] = df['gender'].astype('category')

res = df.groupby(['value_text', 'gender']).count()\
        .fillna(0).astype(int)\
        .reset_index()

print(res)

      value_text gender  value
0          type2      F      0
1          type2      M      2
2  type2 without      F      1
3  type2 without      M      0

答案 2 :(得分:0)

尝试将.unstack().fillna(0).stack()附加到当前行,如下所示:

frame[frame['value_text'].str.match('Type 2')  |
      frame['value_text'].str.match('Type II diabetes')]\
.groupby(['value_text','gender'])['value_text'].count()\
.unstack().fillna(0).stack()

答案 3 :(得分:0)

最简单的方法是pd.crosstab然后stack

# save your filtered dataframe as an intermediate result, for convenience
type2 = frame[frame.value_text.str.match('Type 2|Type II diabetes')]

pd.crosstab(type2.value_text, type2.gender).stack()