Агрегирование после внешнего соединения с использованием pandas

#python-3.x #pandas #merge

#python-3.x #pandas #слияние

Вопрос:

Я пытаюсь объединить большое количество CSV-файлов с именами игроков и результатами за год в один обзор. У меня есть CSV-файл для каждой команды с именами игроков, датами рождения и результатами за год. В некоторых CSV-файлах отсутствует столбец даты рождения. Я получаю повторяющиеся строки при попытке объединить файлы, в которых отсутствует столбец даты рождения.

Например, для команды А в 2010 году у меня есть следующая таблица результатов, teamA2010 :

     Player    Birthdate  2010
    John Doe  14-3-1999  12
    Jane Doe  15-6-1995  3
  

Результат для той же команды в 2011 году выглядит следующим образом. Обратите внимание, что столбец Даты рождения отсутствует. teamA2011

     Player    2011
    John Doe  2
    Jane Doe  1
    Alice     3
  

То, что я хочу, — это следующая таблица:

     Player    Birthdate  2010 2011
    John Doe  14-3-1999  12   2
    Jane Doe  15-6-1995  3    1
    Alice                     3
  

Я попытался объединить таблицу с помощью внешнего объединения (поскольку новые игроки могут войти в команду в последующие годы), но не уверен, как агрегировать по датам рождения и годам?

     join_on = ["Player", "Birthdate"]
    if "Birthdate" in TeamA2011.columns:
       df = pd.merge(TeamA2010, TeamA2011, how='outer', on=join_on)
    else:
       join_on.remove("Birthdate")
       df = pd.merge(TeamA2010, TeamA2011, how='outer', on=join_on)
       join_on.insert(-1, "Birthdate")
  

Результатом является таблица, подобная приведенной ниже:

     Player    Birthdate  2010 2011
    John Doe  14-3-1999  12   
    John Doe                  2
    Jane Doe  15-6-1995  3    
    Jane Doe                  1
    Alice                     3
  

Ответ №1:

Предполагая, что вы хотите достичь этого

   Player    Birthdate  2010 2011
    John Doe  14-3-1999  12   2
    Jane Doe  15-6-1995  3    1
    Alice                     3
  

Я бы сделал это:

df3 = pd.merge(df1, df2, how="outer", on="Player")
где
df1 is the first df you provided и df2 is the 2nd one

Редактировать
Вам не нужно присоединяться в Bitrtday, даже если есть несколько игроков с одинаковым именем и разной датой дня рождения. Об этом позаботится внешнее соединение. Весь код:

 df1 = pd.DataFrame([["John Doe","14-3-1999","12"],
                ["John Doe", "1-1-1999"],
                ["Jane Doe","15-6-1995","3"]], columns=["Player","Birthday","2010"])

df2 = pd.DataFrame([["John Doe", "2"],["Jane Doe", "1"], ["Alice", "3"]], columns=["Player","2011"])


df3 = pd.merge(df1, df2, how="outer", on="Player")
print(df3)

Out:
     Player   Birthday  2010 2011
0  John Doe  14-3-1999    12    2
1  John Doe   1-1-1999  None    2
2  Jane Doe  15-6-1995     3    1
3     Alice        NaN   NaN    3
  

Ответ №2:

Правильное внешнее соединение:

 df = pd.merge(teamA2010, teamA2011, how="right", on="Player")
  

Вывод:

      Player   Birthday 2010 2011
0  John Doe  14-3-1999   12    2
1  Jane Doe  15-6-1995    3    1
2     Alice        NaN  NaN    3
  

Ответ №3:

Проблема возникла, когда я объединил файлы с днями рождения и без них. В конечном счете, я закончил объединением всех CSV-файлов и агрегированием результатов и дней рождения в конце. Поскольку дни рождения могут оказаться дубликатами или объединенными значениями nan, мне пришлось заменить эти значения.

 df["Birthdate"] = pd.to_datetime(df["Birthdate"])
df["Birthdate"] = df["Birthdate"].dt.strftime('%d %B %Y').astype(str)
group_by.remove("Birthdate")
df = df.groupby(group_by, as_index=False).agg(' '.join)

df["Birthdate"] = df["Birthdate"].str.replace(" nan", "")
df["Birthdate"] = df["Birthdate"].str.replace("nan ", "")
df["Birthdate"].loc[df["Birthdate"].str.count(" ") > 2] = df["Birthdate"].str[0:((df["Birthdate"].str.len() 1)/2).round()]