有没有更快的方法来迭代 Python 中的行来计算特征?
Is there a quicker method for iterating over rows in Python to calculate a feature?
我有一个 Pandas 数据框 df
,它详细说明了玩游戏的玩家的姓名。 Dataframe 有 2 列 'Date' they played a game and their name,按日期排序。
Date
Name
1993-03-28
Tom
1993-03-28
Joe
1993-03-29
Tom
1993-03-30
Joe
我想要完成的是高效地计算每个玩家在当天玩即将到来的游戏之前玩过的游戏数量。
对于上面的示例 Dataframe,计算玩家之前的游戏次数将从 0 开始,如下所示。
Date
Name
Previous Games
1993-03-28
Tom
0
1993-03-28
Joe
0
1993-03-29
Tom
1
1993-03-30
Joe
1
我尝试了以下代码,虽然它们提供了正确的结果,但我的计算机花了很多天 运行。
尝试 1:
for i in range(0, len(df) ):
df['Previous Games'][i] = len( df[ (df['Name'] == df['Name'][i]) & (df['Date'] < df['Date'][i]) ] )
尝试 2:
df['Previous Games'] = [ len( df[ (df['Name'] == df['Name'][i]) & (df['Date'] < df['Date'][i]) ] ) for i in range(0, len(df) ) ]
虽然尝试 2 稍快一些,但仍然不省时,因此我需要帮助寻找更快的方法。
任何时候你将“for”和“pandas”写在任何靠近的地方,你可能做错了什么。
在我看来你想要累计计数:
df["prev_games"] = df.sort_values('Date').groupby('Name').cumcount()
是的,更快的方法应该是避免显式 for 循环。您可以为每个名称对数据框进行分组,然后 .rank
按“日期”排列行:
>>> df["Previous Games"] = df.groupby("Name")["Date"].rank("dense") - 1
添加了 -1 以从 0 开始。
这是一个 pandas 问题,而不是一个 python 问题。
在处理 pandas 数据帧时,有几个选项可以避免 for 循环。最直接的是以下一个:
# To recreate a dummy dataset:
se = pd.date_range(start='2016-01-01', end='2020-12-31', freq='D')
df = pd.DataFrame({"Date": se, "Name": list(np.random.choice(("joe", "bob", "alice"), len(se)))})
# To add the previous games column
df['Previous Games'] = df.apply(lambda row: ((row["Date"] > df["Date"]) * (row["Name"] == df["Name"])).sum(), axis=1)
我有一个 Pandas 数据框 df
,它详细说明了玩游戏的玩家的姓名。 Dataframe 有 2 列 'Date' they played a game and their name,按日期排序。
Date | Name |
---|---|
1993-03-28 | Tom |
1993-03-28 | Joe |
1993-03-29 | Tom |
1993-03-30 | Joe |
我想要完成的是高效地计算每个玩家在当天玩即将到来的游戏之前玩过的游戏数量。
对于上面的示例 Dataframe,计算玩家之前的游戏次数将从 0 开始,如下所示。
Date | Name | Previous Games |
---|---|---|
1993-03-28 | Tom | 0 |
1993-03-28 | Joe | 0 |
1993-03-29 | Tom | 1 |
1993-03-30 | Joe | 1 |
我尝试了以下代码,虽然它们提供了正确的结果,但我的计算机花了很多天 运行。
尝试 1:
for i in range(0, len(df) ):
df['Previous Games'][i] = len( df[ (df['Name'] == df['Name'][i]) & (df['Date'] < df['Date'][i]) ] )
尝试 2:
df['Previous Games'] = [ len( df[ (df['Name'] == df['Name'][i]) & (df['Date'] < df['Date'][i]) ] ) for i in range(0, len(df) ) ]
虽然尝试 2 稍快一些,但仍然不省时,因此我需要帮助寻找更快的方法。
任何时候你将“for”和“pandas”写在任何靠近的地方,你可能做错了什么。
在我看来你想要累计计数:
df["prev_games"] = df.sort_values('Date').groupby('Name').cumcount()
是的,更快的方法应该是避免显式 for 循环。您可以为每个名称对数据框进行分组,然后 .rank
按“日期”排列行:
>>> df["Previous Games"] = df.groupby("Name")["Date"].rank("dense") - 1
添加了 -1 以从 0 开始。
这是一个 pandas 问题,而不是一个 python 问题。
在处理 pandas 数据帧时,有几个选项可以避免 for 循环。最直接的是以下一个:
# To recreate a dummy dataset:
se = pd.date_range(start='2016-01-01', end='2020-12-31', freq='D')
df = pd.DataFrame({"Date": se, "Name": list(np.random.choice(("joe", "bob", "alice"), len(se)))})
# To add the previous games column
df['Previous Games'] = df.apply(lambda row: ((row["Date"] > df["Date"]) * (row["Name"] == df["Name"])).sum(), axis=1)