使用 unstack 查找事件和非事件的计数和百分比

Finding both count and percentage for event and non-events using unstack

我有一个如下所示的数据框

import numpy as np
import pandas as pd
np.random.seed(100)
from feature_engine.encoding import OrdinalEncoder


df = pd.DataFrame({'grade': np.random.choice(list('ABCD'),size=(20)),
                   'dash': np.random.choice(list('PQRS'),size=(20)),
                   'dumeel': np.random.choice(list('QWER'),size=(20)),
                   'dumma': np.random.choice((1234),size=(20)),
                   'target': np.random.choice([0,1],size=(20))
})

我想执行以下操作

a) 事件率 - 为每个输入分类列中的每个唯一值计算 1(来自目标列)的出现百分比

b) 非事件率 - 计算每个输入分类列中每个唯一值的 0 出现百分比(来自目标列)

c) 事件数 - 计算每个输入分类列中每个唯一值的 1(来自目标列)的记录数

d) 非事件数 - 计算每个输入分类列中每个唯一值的 0(来自目标列)的记录数

在 Shubham 的帮助下,我能够使用以下代码计算百分比

cols = df.select_dtypes('object')
df_out = (
    df.melt('target', cols)
      .groupby(['variable', 'target'])['value']
      .value_counts(normalize=True)
      .unstack(1, fill_value=0)
)

但是现在,除了 %,我还想获取分类值中每个唯一值的记录数或记录数

我希望我的输出如下所示

我为您提供了一个工作示例。在尝试使用 aggregate method 之后,我意识到这样做是最简单的:

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'grade': np.random.choice(list('ABCD'), size=(20)),
    'dash': np.random.choice(list('PQRS'), size=(20)),
    'dumeel': np.random.choice(list('QWER'), size=(20)),
    'dumma': np.random.choice((1234), size=(20)),
    'target': np.random.choice([0, 1], size=(20))
})

cols = df.select_dtypes('object')
df_out = df.melt('target', cols)

df_out.target = pd.Categorical(df_out.target, [0, 1])  # This must be made sure
df_out.value = pd.Categorical(df_out.value, list('ABCDPQRSWE'))  # This must be made sure

df_out = pd.concat(
   [df_out.groupby(['variable', 'target']).value_counts(normalize=flag).unstack('target') 
   for flag in [True, False]], axis=1, keys=['%-event', '#-event'])

正如我在代码中提到的那样,要使它起作用,适当的列是分类的是必要的。

之后您可能想重命名列 MultiIndex

df_out.columns = ['%-no_event', '%-event', '#-no_event', '#-event']

但请注意顺序!

结果

| variable | value | %-no_event | %-event | #-no_event | #-event
| --- | ---| --- | --- | --- | ---|

这是一种方法:

  • Select 分类列 (cols)
  • Melttarget 作为 id 变量和 cols 作为值变量的数据框
  • 使用 groupby + value_counts
  • 创建频率 table (counts)
  • 标准化 counts table 沿列轴创建 (counts_norm)
  • 连接 countscounts_norm
  • 使用堆栈重塑数据帧,取消堆栈
cols = df.select_dtypes('object')
counts = (
    df.melt('target', cols)
      .groupby(['variable', 'target'])['value']
      .value_counts().unstack()
)
counts_norm = counts.div(counts.sum(1), axis=0)
df_out = pd.concat([counts, counts_norm], keys=['N', '%_N'])\
                      .stack().unstack([0, 2], fill_value=0)

print(df_out)
                  N       %_N     
target            0    1    0    1
variable value                    
dash     P      4.0  3.0  0.4  0.3
         Q      2.0  3.0  0.2  0.3
         R      2.0  1.0  0.2  0.1
         S      2.0  3.0  0.2  0.3
dumeel   E      2.0  2.0  0.2  0.2
         Q      1.0  0.0  0.1  0.0
         R      4.0  6.0  0.4  0.6
         W      3.0  2.0  0.3  0.2
grade    A      4.0  2.0  0.4  0.2
         B      0.0  2.0  0.0  0.2
         C      4.0  3.0  0.4  0.3
         D      2.0  3.0  0.2  0.3