首页 > 解决方案 > 在另一列上使用 groupBy 为 nan 添加模式值

问题描述

我在年份列中有一些 nan 单元格。我认为最好设置按行业类型分组的年度模式。

df
ID  Name     Industry    Year   Employees Expenses   Profit
1   E-Zim    Health      2019   320       1,130,700  8553827
2   Daltfase Software    NaN    78        804,035    13212508
3   Hotlane  Government  2012   87        1,044,375  8701897
4   Latho    Health      NaN    103       4,631,808  10727561
5   Lambam   IT Services 2015   210       4,374,841  4193069
6   Quozap   Health      2008   21        4,626,275  8179177
7   Tampware Health      2008   13        2,127,984  3259485

对于模式值,我做了:

df_mode_year = df.groupby('Industry')['Year'].apply(lambda x: x.mode().iloc[0])
df_mode_year

Industry
Government             2012
Health                 2008
IT Services            2015
Software

然后修改我的df,我试过了

  1. df['年份'].fillna(df_mode_year)
  2. df['Year'] = df['Year'].fillna(df_mode_year[df['Industry']=='Health'])

但是这两个都没有影响最终的 df 。

预期输出:

df
ID  Name     Industry    Year   Employees Expenses   Profit
1   E-Zim    Health      2019   320       1,130,700  8553827
2   Daltfase Software    NaN    78        804,035    13212508
3   Hotlane  Government  2012   87        1,044,375  8701897
4   Latho    Health      2008   103       4,631,808  10727561
5   Lambam   IT Services 2012   210       4,374,841  4193069
6   Quozap   Health      2008   21        4,626,275  8179177
7   Tampware Health      2008   13        2,127,984  3259485

我究竟做错了什么?非常感谢。

标签: pythonpandasdata-cleaning

解决方案


您可以使用.transform()而不是.apply(),它将返回与df相同长度的一系列,每个组的模式

mode = df.groupby('Industry').Year
mode = mode.transform(lambda x: x.mode().squeeze())
df.update(mode, overwrite=False)

.update()操作总是在原地完成并返回None


编辑

如果所有行业至少有一年,则第一部分中的代码可以正常工作,但是.transform(lambda x: x.mode().squeeze())当它遇到仅NaN作为值的组时似乎会引发错误。如果这是数据中的一种可能性,那么最简单的方法是采用您的方法来按行业汇总模式:

mode = df.groupby('Industry').Year.apply(lambda x: x.mode().squeeze())

现在的问题是.squeeze()返回一个空的 Series 并且.iloc[0](如在您的原始代码中)引发异常。

>>> print(mode.apply(type))

Industry
Government                 <class 'numpy.float64'>
Health                     <class 'numpy.float64'>
IT Services                <class 'numpy.float64'>
Software       <class 'pandas.core.series.Series'>
Name: Year, dtype: object

>>> mode = df.groupby('Industry').Year.apply(lambda x: x.mode().iloc[0])
Traceback ...
IndexError: single positional indexer is out-of-bounds

所以现在我们需要修复那个软件价值。由于它是一个可迭代的,它不能被替换,但它可以被迭代:

mode = mode.explode()

现在模式就像我们需要它一样

>>> print(mode)
Industry
Government     2012
Health         2008
IT Services    2015
Software        NaN
Name: Year, dtype: object

对于晚上的最后一招:

df = df.merge(mode, on='Industry') # default suffixes: ['_x', '_y']
mode = df.pop('Year_y').rename('Year')
df.rename({'Year_x': 'Year'}, axis=1, inplace=True)
df.update(mode, overwrite=False)

最终输出

   ID      Name     Industry  Year  Employees   Expenses    Profit
0   1     E-Zim       Health  2019        320  1,130,700   8553827
1   4     Latho       Health  2008        103  4,631,808  10727561
2   6    Quozap       Health  2008         21  4,626,275   8179177
3   7  Tampware       Health  2008         13  2,127,984   3259485
4   2  Daltfase     Software   NaN         78    804,035  13212508
5   3   Hotlane   Government  2012         87  1,044,375   8701897
6   5    Lambam  IT Services  2015        210  4,374,841   4193069

请注意软件如何保持不变NaN并且健康状况仅NaN更新


推荐阅读