Создавайте новые строки на основе максимального количества строк столбца

#python #pandas #dataframe

Вопрос:

Поэтому я пытаюсь создать новые данные во временном ряду на основе прошлых данных. Например, у меня здесь есть данные об игроках, каждая строка которых является статистикой, накопленной в определенном возрасте. Я хочу создать новую строку во фрейме данных, в которой я увеличу максимальный возраст на единицу, а затем возьму среднее значение столбца sa и ga за два года до этого.

Вот данные

 import pandas as pd  data = [['Adam Wilcox', 8476330, 25, 14.0, 0.0],  ['Adin Hill', 8478499, 21, 129.0, 14.0],  ['Adin Hill', 8478499, 22, 322.0, 32.0],  ['Adin Hill', 8478499, 23, 343.0, 28.0],  ['Adin Hill', 8478499, 24, 530.0, 46.0],  ['Adin Hill', 8478499, 25, 237.0, 26.0],  ['Al Montoya', 8471219, 24, 120.0, 9.0],  ['Al Montoya', 8471219, 26, 585.0, 46.0],  ['Al Montoya', 8471219, 27, 832.0, 89.0],  ['Al Montoya', 8471219, 28, 168.0, 17.0]]  model_df = pd.DataFrame(data,   columns=['player', 'player_id', 'season_age', 'sa', 'ga'])  

Например, то, что я хотел бы создать ['Al Montoya', 8471219, 29, 500, 53] (помните, что последние два значения-это среднее sa ga значение столбцов и в возрасте 28 и 27 лет).

Я сделал это, используя iterrows и создав новый фрейм данных и добавив вот так:

 max_ages = model_df.groupby(['player', 'player_id'])[['season_age']].max().reset_index() added_ages = [] for player in max_ages.iterrows():   row = [player[1][0],  player[1][1],  player[1][2]   1,   (model_df[(model_df['player_id'] == player[1][1]) amp;  (model_df['season_age'] == player[1][2] - 1)]['sa'].sum()    model_df[(model_df['player_id'] == player[1][1]) amp;  (model_df['season_age'] == player[1][2] - 2)]['sa'].sum())/2,  (model_df[(model_df['player_id'] == player[1][1]) amp;  (model_df['season_age'] == player[1][2] - 1)]['ga'].sum()    model_df[(model_df['player_id'] == player[1][1]) amp;  (model_df['season_age'] == player[1][2] - 2)]['ga'].sum())/2  ]  added_ages.append(row)  added_ages_df = pd.DataFrame(added_ages,   columns=['player', 'player_id', 'season_age', 'sa', 'ga']) model_df = pd.concat([model_df, added_ages_df])  

Очевидно, что это решение adhoc, которое очень хрупкое, мой вопрос в том, есть ли встроенный способ pandas сделать это без использования iterrows

Ожидаемый фрейм данных будет выглядеть следующим образом, его легче представить в виде списка

 data = [['Adam Wilcox', 8476330, 25, 14.0, 0.0],  ['Adin Hill', 8478499, 21, 129.0, 14.0],  ['Adin Hill', 8478499, 22, 322.0, 32.0],  ['Adin Hill', 8478499, 23, 343.0, 28.0],  ['Adin Hill', 8478499, 24, 530.0, 46.0],  ['Adin Hill', 8478499, 25, 237.0, 26.0],  ['Adin Hill', 8478499, 26, 502, 36],  ['Al Montoya', 8471219, 24, 120.0, 9.0],  ['Al Montoya', 8471219, 26, 585.0, 46.0],  ['Al Montoya', 8471219, 27, 832.0, 89.0],  ['Al Montoya', 8471219, 28, 168.0, 17.0],  ['Al Montoya', 8471219, 29, 500, 53]]  

Комментарии:

1. Было бы более простым решением получить ваши уникальные имена / идентификаторы игроков, создать фрейм данных оболочки с увеличением возраста для каждого игрока от минимального возраста до максимального возраста, независимо от того, что это такое, затем объединить начальный фрейм данных и рассчитать средние значения? Является ли цель, чтобы у каждого игрока был одинаковый минимальный и максимальный возраст, или вы просто хотите добавить 2 дополнительные строки для каждого игрока?

2. Пожалуйста, опубликуйте свой ожидаемый выходной кадр данных

3. @sammywemmy опубликовал

Ответ №1:

Вы можете определить вызываемую функцию add_row и передать ее группе. Я предполагаю, что если у игрока нет данных за два года, вы захотите, чтобы столбцы sa и ga были заполнены NaN :

 def add_row(x):  last_row = x.iloc[-1]  last_row['season_age'] = last_row['season_age'] 1  if len(x) lt; 2:  last_row['sa'], last_row['ga'] = float("nan"), float("nan")  return x.append(last_row)  else:  last_row['sa'], last_row['ga'] = x[['sa','ga']].iloc[-2:].mean()  return x.append(last_row)  new_model_df = model_df.groupby("player").apply(add_row).reset_index(drop=True)  

Выход:

 gt;gt;gt; new_model_df  player player_id season_age sa ga 0 Adam Wilcox 8476330 25 14.0 0.0 1 Adam Wilcox 8476330 26 NaN NaN 2 Adin Hill 8478499 21 129.0 14.0 3 Adin Hill 8478499 22 322.0 32.0 4 Adin Hill 8478499 23 343.0 28.0 5 Adin Hill 8478499 24 530.0 46.0 6 Adin Hill 8478499 25 237.0 26.0 7 Adin Hill 8478499 26 383.5 36.0 8 Al Montoya 8471219 24 120.0 9.0 9 Al Montoya 8471219 26 585.0 46.0 10 Al Montoya 8471219 27 832.0 89.0 11 Al Montoya 8471219 28 168.0 17.0 12 Al Montoya 8471219 29 500.0 53.0  

Ответ №2:

Выполните некоторые вычисления для сгруппированного объекта и объедините результат с model_df:

 grouper = ['player', 'player_id'] grouped = model_df.groupby(grouper, sort = False) tail = grouped.nth(-1) # get the last row per group tail = tail.assign(season_age = tail.season_age   1) # get the average of the last two columns with rolling # a second groupby is called here to get single rows per group sa_ga = (group[['sa', 'ga']]  .rolling(2)  .mean()  .groupby(grouper)  .nth(-1)  )  tail = tail.assign(**sa_ga).reset_index()  # final output (pd.concat([model_df, tail])  .sort_values(grouper, ignore_index = True) )   player player_id season_age sa ga 0 Adam Wilcox 8476330 25 14.0 0.0 1 Adam Wilcox 8476330 26 NaN NaN 2 Adin Hill 8478499 21 129.0 14.0 3 Adin Hill 8478499 22 322.0 32.0 4 Adin Hill 8478499 23 343.0 28.0 5 Adin Hill 8478499 24 530.0 46.0 6 Adin Hill 8478499 25 237.0 26.0 7 Adin Hill 8478499 26 383.5 36.0 8 Al Montoya 8471219 24 120.0 9.0 9 Al Montoya 8471219 26 585.0 46.0 10 Al Montoya 8471219 27 832.0 89.0 11 Al Montoya 8471219 28 168.0 17.0 12 Al Montoya 8471219 29 500.0 53.0  

Ответ №3:

Вы можете попробовать что-то вроде приведенного ниже.

 df_new = df.shift()  df_new['season_age'] = df['season_age'].max()  1  df_new[['sa','ga']] = df[['sa','ga']].rolling(2).mean()  

Комментарии:

1. Это не работает, он перезаписывает season_age столбец со всеми одним значением и неправильно вычисляет добавленную строку Addin Hill