【问题标题】:Pandas - how to sum X last values from 2 columns based on the conditionPandas - 如何根据条件对 2 列中的 X 个最后一个值求和
【发布时间】:2020-04-01 23:42:17
【问题描述】:

最近我开始学习 Pandas。我真的试图找到解决方案,但找不到。这就是问题所在。

我有一个数据框:简单的足球数据。 对于每支球队,我想知道他们在前 2 场比赛中进了多少球;不管他们是主队还是客队。所以我必须为每个团队从 2 个不同的列中汇总特定数量的值。

样本数据:

import pandas as pd
data = [['2018-02-03', 'manutd', 'chelsea', 3, 1], ['2018-02-08', 'arsenal', 'liverpool', 1, 1], 
        ['2018-01-12', 'chelsea', 'westham', 2, 0], ['2018-01-12', 'liverpool', 'manutd', 0, 2], 
        ['2018-03-15', 'arsenal', 'chelsea', 2, 2], ['2018-02-20', 'manutd', 'brighton', 0, 0], 
        ['2018-04-01', 'westham', 'fulham', 1, 0], ['2018-03-15', 'manutd', 'westham', 2, 1]] 
df = pd.DataFrame(data, columns = ['event_time', 'home_team', 'away_team', 'home_goals', 'away_goals'])
df['event_time'] = pd.to_datetime(df['event_time'])
df.sort_values(['event_time'],inplace=True, ascending=False)
print(df)


  event_date  home_team  away_team  home_goals  away_goals
6 2018-04-01    westham     fulham           1           0
4 2018-03-15    arsenal    chelsea           2           2
7 2018-03-15     manutd    westham           2           1
5 2018-02-20     manutd   brighton           0           0
1 2018-02-08    arsenal  liverpool           1           1
0 2018-02-03     manutd    chelsea           3           1
2 2018-01-12    chelsea    westham           2           0
3 2018-01-12  liverpool     manutd           0           2

我想要达到的目标:

  event_time  home_team  away_team  home_goals  away_goals  h_goals_previous_2  a_goals_previous_2
6 2018-04-01    westham     fulham           1           0                  1                  NaN
4 2018-03-15    arsenal    chelsea           2           2                  1                    3
7 2018-03-15     manutd    westham           2           1                  3                    0
5 2018-02-20     manutd   brighton           0           0                  5                  NaN
1 2018-02-08    arsenal  liverpool           1           1                NaN                    0
0 2018-02-03     manutd    chelsea           3           1                  2                      2
2 2018-01-12    chelsea    westham           2           0                NaN                  NaN
3 2018-01-12  liverpool     manutd           0           2                NaN                  NaN

说明: - 2018-03-15 阿森纳与切尔西一起比赛。在之前的2场比赛中,切尔西一共打进3球:客队打进1球,主队打进2球。 - 之前的一些进球是南,因为我们没有之前比赛的数据。

我试图通过逐个团队迭代来做到这一点,并且我为每个团队构建了一个排序的 df 子集,然后可以聚合这些值,但觉得这不是最好的解决方案,可以使用漂亮的 Pandas 表达式来完成:

teams = pd.unique(df[['home_team', 'away_team']].values.ravel('K'))
for team in teams:
    print(team)
    team_df = df[(df['home_team']==team) | (df['away_team']==team)]
    team_df.sort_values(['event_date'],inplace=True, ascending=False)
    print(team_df)

如何在不编写循环和 if 的情况下做到这一点?

【问题讨论】:

  • 你能解释一下“不管他们是主队还是客队”是什么意思吗?如果这是真的,那么为什么你有两个 goals_previous_2 列。一个在家,一个在外。此外,如果您想要更快的反馈,我建议您完成这两列并提供所需的输出。
  • 输出已更新。有 2 个goals_previous_2,因为我想计算主队和客队以及他们在前 2 场比赛中的进球数。计算说明: - 2018-03-15 阿森纳与切尔西交手。在之前的2场比赛中,切尔西一共打进3球:客队打进1球,主队打进2球。 - 之前的一些进球是南,因为我们没有之前比赛的数据。

标签: pandas numpy data-science


【解决方案1】:

方法一:pd.wide_to_long:

#Create a df2 with index like a column a rename the columns to apply:
# pd.wide_to_long

df2=df.set_index('event_time',append=True)
df2.columns=[''.join(name[::-1]) for name in  df2.columns.str.split('_')]
df2.columns=df2.columns.str.replace('home','1').str.replace('away','2')
df2=df2.reset_index()

#Using pd.wide_to_long
df_long=( pd.wide_to_long(df2,['team','goals'],i='level_0',j='key')
          .sort_values('event_time',ascending=False) )
print(df_long)


            event_time       team  goals
level_0 key                             
6       1   2018-04-01    westham      1
        2   2018-04-01     fulham      0
4       1   2018-03-15    arsenal      2
7       1   2018-03-15     manutd      2
4       2   2018-03-15    chelsea      2
7       2   2018-03-15    westham      1
5       1   2018-02-20     manutd      0
        2   2018-02-20   brighton      0
1       1   2018-02-08    arsenal      1
        2   2018-02-08  liverpool      1
0       1   2018-02-03     manutd      3
        2   2018-02-03    chelsea      1
2       1   2018-01-12    chelsea      2
3       1   2018-01-12  liverpool      0
2       2   2018-01-12    westham      0
3       2   2018-01-12     manutd      2

#calculating the sum
groups_goals=df_long.groupby('team')['goals']
df_long=df_long.assign(value_2_sum=groups_goals.shift(-1)+groups_goals.shift(-2))

#Getting goals previous columns
goals_previous=df_long.pivot_table(index='level_0',columns='key',values='value_2_sum',dropna=False)

df[['h_goals_previous_2',  'a_goals_previous_2']]=goals_previous
print(df)

方法二:DataFrame.melt

cols=['h_goals_previous_2',  'a_goals_previous_2']
df2=( df.reset_index()
        .melt(['event_time','home_team','away_team','index'])
        .sort_values('event_time',ascending=False) )
df2['team']=df2['home_team'].mask(df2['variable'].eq('away_goals'),df2['away_team'])

groups_goals=df2.groupby('team')['value']

df2['value_2']=groups_goals.shift(-2)+groups_goals.shift(-1)
df[cols]=( df2.pivot_table(columns='variable',index='index',values='value_2',dropna=False)
              .sort_index(axis=1,ascending=False) )
print(df)

输出:

  event_time  home_team  away_team  home_goals  away_goals  \
6 2018-04-01    westham     fulham           1           0   
4 2018-03-15    arsenal    chelsea           2           2   
7 2018-03-15     manutd    westham           2           1   
5 2018-02-20     manutd   brighton           0           0   
1 2018-02-08    arsenal  liverpool           1           1   
0 2018-02-03     manutd    chelsea           3           1   
2 2018-01-12    chelsea    westham           2           0   
3 2018-01-12  liverpool     manutd           0           2   

   h_goals_previous_2  a_goals_previous_2  
6                 1.0                 NaN  
4                 NaN                 3.0  
7                 3.0                 NaN  
5                 5.0                 NaN  
1                 NaN                 NaN  
0                 NaN                 NaN  
2                 NaN                 NaN  
3                 NaN                 NaN  

注意NaN值比较多,因为我只使用了你的数据框中显示的行

【讨论】:

  • 谢谢!它有效,我学到了很多东西。我有一个关于为 N 之前的比赛参数化它的问题,例如。最后 8 个用于大型数据集。
  • 可以用什么代替value_2_sum=groups_goals.shift(-1)+groups_goals.shift(-2)?我尝试使用groups_goals.shift(-8).rolling(8).sum(),但不能与 groupedby 系列一起正常工作。如果我在 df['goals'] 上直接使用 shift&rolling,那么它的总和是正确的(但这不是我想要实现的),但是在将它用于 groups_goals 之后,我得到了“奇怪”的结果——可能是索引的问题。
猜你喜欢
  • 1970-01-01
  • 2019-12-23
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
  • 2021-05-12
  • 1970-01-01
  • 2021-10-12
  • 2021-09-16
相关资源
最近更新 更多