如何在pandas中正确添加多个系列?

How to add multiple series in pandas correctly?

我有一个问题。 在我的数据框中,我将(游戏玩家的)名字存储在四列 W1、W2、W3、W4 中,用于赢得一轮的四名玩家以及输掉一轮的 L1、L2、L3、L4。还有一列 WP 表示赢分(取决于所玩的地图)和 LP 表示输分,即 -WP。 这些将是所讨论的 10 列的 .head() 。索引是玩的回合。它基本上是 history/tracker 过去的游戏。

{'W1': {0: nan, 1: 'Matthi', 2: 'Vain', 3: 'Matthi', 4: 'Markus'},
 'W2': {0: nan, 1: 'Paddy', 2: 'Marvin', 3: 'Jonas', 4: 'Marvin'},
 'W3': {0: nan, 1: 'Max', 2: 'Paddy', 3: 'Vain', 4: 'Johann'},
 'W4': {0: nan, 1: nan, 2: 'Max', 3: 'Johannes', 4: 'Max'},
 'WP': {0: nan, 1: 5.0, 2: 5.0, 3: 3.0, 4: 4.0},
 'L1': {0: nan, 1: 'Timi', 2: 'Matthi', 3: 'Timi', 4: 'Matthi'},
 'L2': {0: nan, 1: 'Markus', 2: 'Timi', 3: 'Markus', 4: 'Timi'},
 'L3': {0: nan, 1: 'Marvin', 2: 'Markus', 3: 'Marvin', 4: 'Vain'},
 'L4': {0: nan, 1: nan, 2: 'Johannes', 3: 'Nille', 4: 'Paddy'},
 'LP': {0: nan, 1: -5.0, 2: -5.0, 3: -3.0, 4: -4.0}}

我想做的是进行排名,例如,对于“Max”,每次他在任一获胜玩家列中时都添加 WP,并在每次他在任一失败者列中减去 LP玩家专栏。

我希望我能做到这一点:

df.groupby("W1")["WP"].sum()+ df.groupby("W2")["WP"].sum()+ df.groupby("W3")["WP"].sum()+ df.groupby("W4")["WP"].sum()+ df.groupby("L1")["LP"].sum()+ df.groupby("L2")["LP"].sum()+ df.groupby("L3")["LP"].sum()+ df.groupby("L4")["LP"].sum()

但这给了我(很多“不应该”存在的 NaN,这当然是整个 df):

Funkey       NaN
Johann       NaN
Johannes   -16.0
Jonas       22.0
Markus       NaN
Marvin      41.0
Matthi       NaN
Max         38.0
Nille        NaN
Paddy       -2.0
Timi         NaN
Vain       -16.0
dtype: float64

奇怪的是(对我来说)所有不是 NaN 的值都是正确的。

现在,我认为问题在于四列中的名称有些随机。这也意味着并非每一列都具有所有名称。例如。 “Max”有时会出现在W1,有时会出现在W2,但可能永远不会出现在W3或W4。

我还认为我可以用:

pd.Series.add(df.groupby("W1")["WP"].sum(), df.groupby("W2")["WP"].sum(), etc., fill_value=0)

但是,如果我放置三个以上的 groupby,就会出现错误。

我怎样才能实现我想做的事情?

您可以使用 melt 来展平数据框并计算每个玩家的分数。

df1 = df.melt(['WP', 'LP'], var_name='W/L', value_name='Player').dropna()
df1['Points'] = np.where(df1['W/L'].str[0] == 'W', df1['WP'], df1['LP'])
out = df1.groupby('Player', as_index=False)['Points'].sum() \
         .sort_values('Points', ascending=False, ignore_index=True)

输出

Player Points
Max 14
Paddy 6
Johann 4
Vain 4
Jonas 3
Marvin 1
Matthi -1
Johannes -2
Nille -3
Markus -9
Timi -17

检查 df1 以查看中间数据帧。

IIUC,melt 重塑,根据列名计算点(如果以 W 开头),以及 grouby+sum:

import numpy as np
(df
 .melt(id_vars=['WP','LP'], value_name='name')
 .assign(points=lambda d: np.where(d['variable'].str.startswith('W'), d['WP'], d['LP']))
 .groupby('name')['points'].sum()
 )

输出:

name
Johann       4.0
Johannes    -2.0
Jonas        3.0
Markus      -9.0
Marvin       1.0
Matthi      -1.0
Max         14.0
Nille       -3.0
Paddy        6.0
Timi       -17.0
Vain         4.0
Name: points, dtype: float64