根据条件从两个数据框中提取值

时间:2020-02-01 14:35:12

标签: python pandas dataframe

我有两个数据框:

df1 = pd.DataFrame({'player': ['AB','AB','AB'], 'contract_length':[2,3,1], 'year': [1998,2000,2003]})
df2 = pd.DataFrame({'player': ['AB','AB','AB','AB','AB','AB'], 'year':[1998,1999,2000,2001,2002,2003],'player_value': [4,3,7,10,9,2]})

df1
  player    contract_length     year
0   AB            2             1998
1   AB            3             2000
2   AB            1             2003

df2
    player  year    player_value
0   AB      1998    4
1   AB      1999    3
2   AB      2000    7
3   AB      2001    10
4   AB      2002    9
5   AB      2003    2

第一个数据框列出了玩家已签订的合同。例如:1998年,他签订了为期2年的合同。

第二个数据框列出了各个季节以及我为每个季节设置的值。

我正在尝试在df1上添加新列,以根据合同年和合同期限将df2中的玩家总值相加。例如,df1的第一行是1998年和2年。因此,该值将是7,来自1998年和1999年(2年合同)的球员值4和3。

我似乎无法弄清楚为什么它没有返回正确的结果:

for i,row in df1.iterrows():
    year_list = list(range(row['year'],((row['year'])+(row['contract_length']))))
    player = row['player']
    df = pd.DataFrame(columns=['player_value'])
    for year in year_list:
        player_value = df2.loc[(df2['player']==player) & (df2['year'] == year),['player_value']]
        df1['contract_value'] = sum(df['player_value'])

此返回:

player  contract_length year    contract_value
0   AB     2            1998    0
1   AB     3            2000    0
2   AB     1            2003    0

何时应该:

player  contract_length year    contract_value
0   AB     2            1998    7
1   AB     3            2000    26
2   AB     1            2003    2

没有返回错误。只是最后一列中的零。

3 个答案:

答案 0 :(得分:2)

使用合同期限获取每年的切片,然后求和palyer_value

import pandas as pd

df1 = pd.DataFrame({'player': ['AB','AB','AB'], 'contract_length':[2,3,1], 'year': [1998,2000,2003]})
df2 = pd.DataFrame({'player': ['AB','AB','AB','AB','AB','AB'], 'year':[1998,1999,2000,2001,2002,2003],'player_value': [4,3,7,10,9,2]})

data = []
for index, row in df1.iterrows():
    contract_data = df2[(df2['year'] >= row['year']) & (df2['year'] <= row['year']+row['contract_length']-1)]
    sum = contract_data['player_value'].sum()
    data.append(sum)

df1['contract_value'] = data

输出:

  player  contract_length  year  contract_value
0     AB                2  1998               7
1     AB                3  2000              26
2     AB                1  2003               2

答案 1 :(得分:1)

根据contract_length考虑repeating数据帧,然后assigning另一列adds基于组的年份,然后与第二列合并:

final = (df1.loc[df1.index.repeat(df1['contract_length'])]
        .assign(year1 = lambda x: x['year']+x.groupby('year').cumcount())
        .merge(df2, left_on = ['player','year1'],right_on = ['player','year']
        ,suffixes = ('','_y')).groupby(['player','contract_length','year']
        ,sort=False,as_index=False)['player_value'].sum())

  player  contract_length  year  player_value
0     AB                2  1998             7
1     AB                3  2000            26
2     AB                1  2003             2

将其分解为2个步骤:

m = df1.loc[df1.index.repeat(df1['contract_length'])].assign(year1 = lambda x:
             x['year']+x.groupby('year').cumcount())
final1 = (m.merge(df2,left_on = ['player','year1'],right_on=['player','year']
         ,suffixes=('','_y').groupby(['player','contract_length','year']
          ,sort=False,as_index=False)['player_value'].sum())

   player  contract_length  year  player_value
0     AB                2  1998             7
1     AB                3  2000            26
2     AB                1  2003             2

就这样,您就知道我们正在将第二个数据框与以下内容合并:

print(m)

  player  contract_length  year  year1
0     AB                2  1998   1998
0     AB                2  1998   1999
1     AB                3  2000   2000
1     AB                3  2000   2001
1     AB                3  2000   2002
2     AB                1  2003   2003

答案 2 :(得分:0)

另一种尝试,使用.explode()

df1['contract_value'] = pd.merge(
        df1.assign(years=df1.apply(lambda x: [*range(x['year'], x['year'] + x['contract_length'])] ,axis=1)).explode('years'),
        df2, left_on=['player', 'years'], right_on=['player', 'year']
    ).groupby(['player', 'year_x'], as_index=False)['player_value'].sum()['player_value']

print(df1)

打印:

  player  contract_length  year  contract_value
0     AB                2  1998               7
1     AB                3  2000              26
2     AB                1  2003               2