【问题标题】:Group by pandas dataframe and impute missing values按熊猫数据框分组并估算缺失值
【发布时间】:2021-08-23 06:17:27
【问题描述】:

我正在创建一个新的计算 pandas 列,但是,我想排除某些行,并计算新列的值。然后填充排除行的值,我想通过df1.groupby['City'] 对数据帧进行子集化,并计算平均值以应用回原始数据帧中的new col。

   df1 = pd.DataFrame({
                        'City': ['SF','NYC','SF','NYC','SF','CHI','LA','LA','CHI'], 
                        'Val': [2,4,0,0,7,4,3,5,6],
                        'Val1': [1,1,1,1,1,1,1,1,1] 
                       })

 
   df1['new col'] = np.nan

   for name, group in df.groupby(['City']):

       # Create Boolean Index
       m = group['Val'] != 0

       # Calculate rev_per_unit from grouped dataframe `group`
       stat = group.loc[m, 'Val'] / group.loc[m, 'Val1']


       # Assign stat to `df` at index locations where `Val` is 0 in group
       df.loc[group[~m].index, ''] = group['new col'].mean()

预期输出:

df1 = pd.DataFrame({
                        'City': ['SF','NYC','SF','NYC','SF','CHI','LA','LA','CHI'], 
                        'Val': [2,4,0,0,7,4,3,5,6],
                        'Val1': [1,1,1,1,1,1,1,1,1],
                        'new_col: [2,4,4.5,2,7,4,3,5,6]
                       })

新列是df1['Val] / df1['Val1'] 的计算列,不包括df['Val'] == 0,然后我将new_col 估算为df['Val'] == 0 作为分组均值的行。

【问题讨论】:

  • 预期输出是什么?你的意思是df.loc[group[~m].index, ''] = stat.mean()?
  • new_col 将是该组的平均值,计算后不包括。 df['Val'] 中的 0。 @HenryEcker 用预期的输出更新了问题。
  • 基本上,缺失值是new_col 中每个组的值的平均值。

标签: python pandas


【解决方案1】:

第一组new_col 到Val/Val1:

df1['new_col'] = df1['Val'] / df1['Val1']

然后使用groupby.transform 计算分组平均值(将 0 设置为 nan 以忽略这些行):

means = df1['new_col'].replace(0, np.nan).groupby(df1['City']).transform('mean')

# [4.5, 4.0, 4.5, 4.0, 4.5, 5.0, 4.0, 4.0, 5.0]
# Length: 9, dtype: float64

最后用分组均值估算 0 个位置:

  • 要么使用DataFrame.loc:

    df1.loc[df1['Val'].eq(0), 'new_col'] = means
    
  • 或Series.mask:

    df1['new_col'] = df1['new_col'].mask(df1['Val'].eq(0), means)
    
  • 或Series.fillna:

    df1['new_col'] = df1['new_col'].replace(0, np.nan).fillna(means)
    

完全是这样:

df1['new_col'] = df1['Val'] / df1['Val1']
means = df1['new_col'].replace(0, np.nan).groupby(df1['City']).transform('mean')
df1.loc[df1['Val'].eq(0), 'new_col'] = means

#   City  Val  Val1  new_col
# 0   SF    2     1      2.0
# 1  NYC    4     1      4.0
# 2   SF    0     1      4.5
# 3  NYC    0     1      4.0
# 4   SF    7     1      7.0
# 5  CHI    4     1      4.0
# 6   LA    3     1      3.0
# 7   LA    5     1      5.0
# 8  CHI    6     1      6.0

【讨论】:

  • 不确定预期的输出是否有一些拼写错误,或者我是否误解了这个问题。例如,我无法弄清楚为什么预期的 SF 输出会是 2、3 和 4。第一个和最后一个 SF 值是非零(2 和 7),所以我希望它们的原始值被保留。中间的 SF 值为零,所以我希望它是 mean([2,7]),即 4.5,所以最终的 SF 输出将是 2、4.5 和 7。这就是 transform+mask 背后的逻辑.
  • 新列是df1['Val] / df1['Val1'] 的计算列,不包括df['Val'] == 0,然后我将new_col 估算为df['Val'] == 0 作为分组方式的行。 @tdy
  • 但我仍然没有看到预期值的来源。比如为什么第三个SF 输出等于4?在该行中,Val/Val1 = 7/1 = 7,因此不应有任何插补,但预期的 df 显示为 4。
  • 那是一个错字。 new_col 的估算值是分组平均值。
猜你喜欢
  • 1970-01-01
  • 2017-10-17
  • 2021-06-08
  • 2019-08-16
  • 2020-06-19
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
  • 2019-08-14
相关资源
最近更新 更多