Добавление значения режима для nan с помощью groupBy в другом столбце - PullRequest
0 голосов
/ 01 августа 2020

У меня есть несколько нанячеек в столбце года. Я подумал, что лучше установить столбец Режим года, сгруппированный по типу отрасли.

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 ['Year']. 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

Что я делаю не так? Большое спасибо.

Ответы [ 2 ]

1 голос
/ 01 августа 2020

Вы можете использовать .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() возвращает пустую серию, а .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

Итак, теперь нам нужно исправить это значение Software. Поскольку это итерация, она не может быть заменена, но ее можно повторить:

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 s

0 голосов
/ 01 августа 2020

Я бы попробовал повернуть и растопить. (Вам может потребоваться сначала преобразовать df_mode_year в карту)

df1 = df.pivot(index = 'ID', columns = 'Industry', values = 'Year').reset_index(drop = True)
df1 = df1.fillna(df_mode_year)
df1 = df1.melt(id_vars = 'ID', var_name='Industry', value_name='Year')

Затем вы можете объединить этот df1 с другими столбцами из df, чтобы получить желаемую таблицу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...