关键列值相同时,可在两行中切换两个值

时间:2019-04-29 11:03:04

标签: python pandas

我有3个棒球比赛的下表。在每场比赛中,我都有两行代表在同一​​场比赛中的两支球队中每一支球队的信息。通过检查列play_homevisitor来知道哪一行是指哪个团队,如果该列有1,则该行与主队(位于hometeam列中)有关,但如果为0,则该行与访问者有关。团队(位于visteam列中)。这是我的数据集df

Game_ID             hometeam    visteam play_homevisitor    Runs_scored
ATL199204090         ATL         SFN           0                13
ATL199204090         ATL         SFN           1                6
ATL199204100         ATL         SFN           0                3
ATL199204100         ATL         SFN           1                6
ATL199204110         ATL         SFN           0                4
ATL199204110         ATL         SFN           1                0

我也有每队的得分。

因此,我需要计算带有runs_allowed的新列,只需在具有相同Game_ID的每两行之间切换runs_scored的值,如下所示:

Game_ID        hometeam visteam play_homevisitor    Runs_scored     Runs_allowed       
ATL199204090    ATL      SFN           0                13                6
ATL199204090    ATL      SFN           1                6                 13
ATL199204100    ATL      SFN           0                3                 6
ATL199204100    ATL      SFN           1                6                 3
ATL199204110    ATL      SFN           0                4                 0
ATL199204110    ATL      SFN           1                0                 4

我有一种可能的方法,但我很好奇您是否有另一种方法可以做到。

我一直在想任何可能的方法,我注意到play_homevisitor列中的序列始终为0、1、0、1,因此我想到了:

  1. 创建两个中间列,将runs_scored移到-1和+1。它将创建列upShift和列downShift。仅分析每对game_D;在upShift中,主队得分的得分会上升,而在DownShift中,访问者队得分的得分会下降。
df['downShift'] = df['Runs_scored'].shift(periods= 1).fillna(0)
df['upShift'] = df['Runs_scored'].shift(periods= -1).fillna(0)
  1. 然后,如果play_homevisitor为0,我将在upShift中拾取该值,否则,如果play_homevisitor为1,我将在downshift中拾取该值
  

df ['Runs_allowed'] = df [['play_homevisitor','downShift',   ['upShift']]。apply(lambda x:x ['upShift']如果x ['play_homevisitor'] == 0   否则x ['downShift'],轴= 1)

3 个答案:

答案 0 :(得分:1)

您可以将groupbyshift结合使用两次。然后使用fillna创建新列:

s1 = df.groupby('Game_ID')['Runs_scored'].shift(-1)
s2 = df.groupby('Game_ID')['Runs_scored'].shift(1)

df['Runs_allowed'] = s1.fillna(s2).astype(int)

print(df)
        Game_ID hometeam visteam  play_homevisitor  Runs_scored  Runs_allowed
0  ATL199204090      ATL     SFN                 0           13             6
1  ATL199204090      ATL     SFN                 1            6            13
2  ATL199204100      ATL     SFN                 0            3             6
3  ATL199204100      ATL     SFN                 1            6             3
4  ATL199204110      ATL     SFN                 0            4             0
5  ATL199204110      ATL     SFN                 1            0             4

答案 1 :(得分:0)

我一直在想任何可能的方法,我注意到play_homevisitor列中的序列始终为0、1、0、1,因此我想到了:

  1. 创建两个中间列,将runs_scored移到-1和+1。它将创建列upShift和列downShift。仅分析每对game_D;在upShift中,主队得分的得分会上升,而在DownShift中,访问者队得分的得分会下降。
df['downShift'] = df['Runs_scored'].shift(periods= 1).fillna(0)
df['upShift'] = df['Runs_scored'].shift(periods= -1).fillna(0)
  1. 然后,如果play_homevisitor为0,我将在upShift中拾取该值,否则,如果play_homevisitor为1,我将在downshift中拾取该值
  

df ['Runs_allowed'] = df [['play_homevisitor','downShift',   ['upShift']]。apply(lambda x:x ['upShift']如果x ['play_homevisitor'] == 0   否则x ['downShift'],轴= 1)

答案 2 :(得分:0)

如果所有对和列均已排序,请使用:

df = df.sort_values(['Game_ID','play_homevisitor'])

m1 = df['play_homevisitor'] == 0
m2 = df['play_homevisitor'] == 1

s1 = df.loc[m1, 'Runs_scored'].values
s2 = df.loc[m2, 'Runs_scored'].values
df.loc[m2, 'Runs_allowed'], df.loc[m1, 'Runs_allowed'] = s1, s2 

print (df)
        Game_ID hometeam visteam  play_homevisitor  Runs_scored  Runs_allowed
0  ATL199204090      ATL     SFN                 0           13           6.0
1  ATL199204090      ATL     SFN                 1            6          13.0
2  ATL199204100      ATL     SFN                 0            3           6.0
3  ATL199204100      ATL     SFN                 1            6           3.0
4  ATL199204110      ATL     SFN                 0            4           0.0
5  ATL199204110      ATL     SFN                 1            0           4.0