我有两个dataframe,一个包含不同的日期和不同的player_id。第二个包含每个球员的评级历史,这意味着它包含不同的日期和不同的player_id和player_rating与一个唯一的id的每一行。
现在,我想通过比较两个DataFrame中的日期列,为第一个DataFrame添加一列,该列具有player_rating的一个值。
例如:
print(df_1)
date player_id
0 2006 1
1 2006 2
2 2012 3
3 2008 2
4 2010 1
print(df_2)
date player_id player_rating
0 2005 1 50
1 2007 2 55
2 2005 3 70
3 2005 2 65
4 2009 1 60
5 2011 2 75
6 2011 3 85
在这里,我应该比较df_1中的第一行与df_2中的第一行和第五行(相同的player_id),然后从df_2中选择具有最新日期且小于df_1中的日期的行。因此,我应该选择第一行并将player_rating设置为50。
最后,我应该得到:print(df_1)
date player_id player_rating
0 2006 1 50
1 2006 2 65
2 2012 3 85
3 2008 2 55
4 2010 1 60
我已经尝试了许多解决方案,并得到以下想法,但相对于一个庞大的数据集(大约一百万行df_1和+100k行df_2)运行需要很多时间:
def get_rating(date, player_id):
return df_2[(df_2['player_id']==player_id) & (df_2['date'] < date)].sort_values(by=['date'], ascending=False).player_rating.iloc[0]
df_1['player_rating'] = [get_rating(x,y) for x, y in zip(df_1['date'], df_1['player_id'])]
有没有更好的方法来节省时间呢?提前谢谢你。
您可能需要测试效率:
(df1.merge(df2, on='player_id', how = 'left', suffixes=(None, '_y'))
.sort_values(['date', 'date_y'])
.query('date > date_y')
.groupby(['date', 'player_id'])
.tail(1)
.drop(columns='date_y')
.sort_index()
)
date player_id player_rating
0 2006 1 50
3 2006 2 65
6 2012 3 85
7 2008 2 55
11 2010 1 60
您可以尝试合并player_id
上的两个数据帧,然后使用有关日期的逻辑。
import pandas as pd
df1 = pd.DataFrame(
{'date': {0: 2006, 1: 2006, 2: 2012, 3: 2008, 4: 2010},
'player_id': {0: 1, 1: 2, 2: 3, 3: 2, 4: 1}})
df2 = pd.DataFrame(
{'date': {0: 2005, 1: 2007, 2: 2005, 3: 2005, 4: 2009, 5: 2011, 6: 2011},
'player_id': {0: 1, 1: 2, 2: 3, 3: 2, 4: 1, 5: 2, 6: 3},
'player_rating': {0: 50, 1: 55, 2: 70, 3: 65, 4: 60, 5: 75, 6: 85}})
<标题>合并df = pd.merge(df1, df2, on=["player_id"])
数据看起来像
date_x player_id date_y player_rating
0 2006 1 2005 50
1 2006 1 2009 60
2 2010 1 2005 50
3 2010 1 2009 60
4 2006 2 2007 55
5 2006 2 2005 65
6 2006 2 2011 75
7 2008 2 2007 55
8 2008 2 2005 65
9 2008 2 2011 75
10 2012 3 2005 70
11 2012 3 2011 85
<标题>过滤器h1> 在你要求date_x
大于date_y
df = df[df["date_x"].gt(df["date_y"])].reset_index(drop=True)
还有
date_x player_id date_y player_rating
0 2006 1 2005 50
1 2010 1 2005 50
2 2010 1 2009 60
3 2006 2 2005 65
4 2008 2 2007 55
5 2008 2 2005 65
6 2012 3 2005 70
7 2012 3 2011 85
使用groupby查找每年的最晚日期
这里我们寻找组中date_y大的索引
grp = df.groupby(["date_x", "player_id"])["date_y"].idxmax()
print(grp)
date_x player_id
2006 1 0
2 3
2008 2 4
2010 1 2
2012 3 7
Name: date_y, dtype: int64
我们用这些索引
进行过滤df = df[df.index.isin(grp.values)].reset_index(drop=True)
看起来像
date_x player_id date_y player_rating
0 2006 1 2005 50
1 2010 1 2009 60
2 2006 2 2005 65
3 2008 2 2007 55
4 2012 3 2011 85
,我们删除列并重命名第一个。
df = df.drop(columns=["date_y"])
.rename(columns={"date_x":"date"})
返回
date player_id player_rating
0 2006 1 50
1 2010 1 60
2 2006 2 65
3 2008 2 55
4 2012 3 85
标题>标题>标题>