Python 3.x 当尝试在计算新列时使用以前的各种行值时,For循环挂起。需要找到一个非for循环解决方案
我有一个650万行的数据集,其中记录了每个用户ID与代币供应商的交互。 数据按“id”和“天数”排序 “天”列是他们加入供应商后的天数 用户获得代币的日期,在Python 3.x 当尝试在计算新列时使用以前的各种行值时,For循环挂起。需要找到一个非for循环解决方案,python-3.x,pandas,Python 3.x,Pandas,我有一个650万行的数据集,其中记录了每个用户ID与代币供应商的交互。 数据按“id”和“天数”排序 “天”列是他们加入供应商后的天数 用户获得代币的日期,在token\u SUPPLY列中提到。 每天使用一个令牌 我想创建一个列,其中提到每行的可用令牌数 我使用的逻辑是: 对于每一行,检查我们是否仍在查看相同的用户“id”。如果是,则检查是否提供了代币,如果是,则保存日数。 对于同一用户的每个后续行,计算可用令牌—提供的令牌数量减去自提供令牌以来经过的天数 currID=0 tokenSupp
token\u SUPPLY
列中提到。
每天使用一个令牌
我想创建一个列,其中提到每行的可用令牌数
我使用的逻辑是:
对于每一行,检查我们是否仍在查看相同的用户“id”。如果是,则检查是否提供了代币,如果是,则保存日数。
对于同一用户的每个后续行,计算可用令牌—提供的令牌数量减去自提供令牌以来经过的天数
currID=0
tokenSupply=0
giveDay=0
for row in df11.itertuples():
if row.id != currID:
tokenSupply = 0
currID= row.id
if row.token_SUPPLY > 0:
giveDay=row.Days
tokenSupply = row.token_SUPPLY
df11.loc[row.Index,"token_onhand"]=tokenSupply
else:
if tokenSupply == 0:
df11.loc[row.Index,"token_onhand"]=0
else:
df11.loc[row.Index,"token_onhand"]=tokenSupply-(row.Days-giveDay)
# For loop doesn't end for more than 50 minutes.
从昨晚开始,我读了很多书,似乎有人建议使用numpy
,但我不知道怎么做,因为我正在学习使用这些东西。另一个建议是@jit
,但我想这只有在我定义一个函数的情况下才有效
另一个建议是矢量化,但我如何有条件地访问行并记住在随后的每一行中使用的供应量?
我确实试过使用np.where
,但它似乎太复杂了,我无法理解它
我也准备好了一些关于赛昂的东西,但我也不知道如何正确地做到这一点
实现我的目标的最佳方法是什么
编辑:添加示例数据和必需的输出列
样本输出数据:
id Days token_SUPPLY give_event token_onhand
190 ID1001 -12 NaN 0 0.0
191 ID1001 -12 NaN 0 0.0
192 ID1001 -3 NaN 0 0.0
193 ID1001 0 5.0 0 5.0
194 ID1001 0 5.0 1 5.0
195 ID1001 6 NaN 0 -1.0
196 ID1001 12 NaN 0 -7.0
197 ID1001 12 NaN 0 -7.0
198 ID1001 13 NaN 0 -8.0
199 ID1001 13 NaN 0 -8.0
当前的最后一列标记不在数据集中,它是实际需要生成的。如果我理解正确: 样本数据:
id Days token_SUPPLY give_event
0 ID1001 -12 NaN 0
1 ID1001 -12 NaN 0
2 ID1001 -3 NaN 0
3 ID1001 0 5.0 0
4 ID1001 0 5.0 1
5 ID1001 6 NaN 0
6 ID1001 12 NaN 0
7 ID1001 12 NaN 0
8 ID1001 13 NaN 0
9 ID1001 13 NaN 0
10 ID1002 -12 NaN 0
11 ID1002 -12 NaN 0
12 ID1002 -3 NaN 0
13 ID1002 0 5.0 0
14 ID1002 0 5.0 1
15 ID1002 6 NaN 0
16 ID1002 12 NaN 0
17 ID1002 12 NaN 0
18 ID1002 13 NaN 0
19 ID1002 13 NaN 0
您可以在token\u Supply
上使用ffill
,并减去Days
。如需了解更多有关id
的信息,请使用groupby
df = pd.read_clipboard()
df['token_onhand'] = df.groupby('id').apply(lambda x: (x['token_SUPPLY'].ffill() - x['Days']).fillna(0)).reset_index(drop=True)
df
结果:
id Days token_SUPPLY give_event token_onhand
0 ID1001 -12 NaN 0 0.0
1 ID1001 -12 NaN 0 0.0
2 ID1001 -3 NaN 0 0.0
3 ID1001 0 5.0 0 5.0
4 ID1001 0 5.0 1 5.0
5 ID1001 6 NaN 0 -1.0
6 ID1001 12 NaN 0 -7.0
7 ID1001 12 NaN 0 -7.0
8 ID1001 13 NaN 0 -8.0
9 ID1001 13 NaN 0 -8.0
10 ID1002 -12 NaN 0 0.0
11 ID1002 -12 NaN 0 0.0
12 ID1002 -3 NaN 0 0.0
13 ID1002 0 5.0 0 5.0
14 ID1002 0 5.0 1 5.0
15 ID1002 6 NaN 0 -1.0
16 ID1002 12 NaN 0 -7.0
17 ID1002 12 NaN 0 -7.0
18 ID1002 13 NaN 0 -8.0
19 ID1002 13 NaN 0 -8.0
这是因为您正在使用for循环,而pandas不能很好地处理这些循环,因此需要使用矢量化解决方案来利用用C/Cython编写的底层代码。为此,您能否发布数据集样本和输出样本?希望我们能够提供一个更为优化的解决方案。@datanoveler添加了示例数据。谢谢,这看起来非常优雅。但是,如果在第0天以外的任何一天提供代币,则这似乎不起作用。他们可以在第20天再次获得代币,或者可能在第-20天获得代币。嘿@michael gardner,只是想看看你是否有基于我的澄清的答案。