gpt4 book ai didi

python - 将 Pandas 数据框中的行和上一行与数百万行进行比较的最快方法

转载 作者:太空狗 更新时间:2023-10-29 16:54:46 31 4
gpt4 key购买 nike

我正在寻找解决方案来加速我编写的用于循环遍历 pandas 数据框并比较当前行和前一行之间的列值的函数。

例如,这是我的问题的简化版本:

   User  Time                 Col1  newcol1  newcol2  newcol3  newcol4
0 1 6 [cat, dog, goat] 0 0 0 0
1 1 6 [cat, sheep] 0 0 0 0
2 1 12 [sheep, goat] 0 0 0 0
3 2 3 [cat, lion] 0 0 0 0
4 2 5 [fish, goat, lemur] 0 0 0 0
5 3 9 [cat, dog] 0 0 0 0
6 4 4 [dog, goat] 0 0 0 0
7 4 11 [cat] 0 0 0 0

目前我有一个函数可以循环并计算“newcol1”的值' 和 ' newcol2 ' 基于是否 ' User ' 自上一行以来发生了变化,并且' Time 中的差异是否存在' 值大于 1。它还会查看存储在 'Col1 中的数组中的第一个值' 和 ' Col2 ' 并更新 ' newcol3 ' 和 ' newcol4 ' 如果这些值自上一行以来发生了变化。

这是我目前正在做的事情的伪代码(因为我已经简化了我没有测试过的问题,但它与我在 ipython notebook 中实际做的非常相似):

 def myJFunc(df):
... #initialize jnum counter
... jnum = 0;
... #loop through each row of dataframe (not including the first/zeroeth)
... for i in range(1,len(df)):
... #has user changed?
... if df.User.loc[i] == df.User.loc[i-1]:
... #has time increased by more than 1 (hour)?
... if abs(df.Time.loc[i]-df.Time.loc[i-1])>1:
... #update new columns
... df['newcol2'].loc[i-1] = 1;
... df['newcol1'].loc[i] = 1;
... #increase jnum
... jnum += 1;
... #has content changed?
... if df.Col1.loc[i][0] != df.Col1.loc[i-1][0]:
... #record this change
... df['newcol4'].loc[i-1] = [df.Col1.loc[i-1][0], df.Col2.loc[i][0]];
... #different user?
... elif df.User.loc[i] != df.User.loc[i-1]:
... #update new columns
... df['newcol1'].loc[i] = 1;
... df['newcol2'].loc[i-1] = 1;
... #store jnum elsewhere (code not included here) and reset jnum
... jnum = 1;

我现在需要将这个函数应用到几百万行,它的速度慢得不可思议,所以我想找出加速它的最佳方法。我听说 Cython 可以提高函数的速度,但我没有使用它的经验(而且我对 pandas 和 python 都是新手)。是否可以将数据帧的两行作为参数传递给函数,然后使用 Cython 来加速它,或者是否有必要创建其中包含“diff”值的新列,以便函数仅读取和写入一次到一行数据框,以便从使用 Cython 中获益?任何其他速度技巧将不胜感激!

(关于使用 .loc,我比较了 .loc、.iloc 和 .ix,这个稍微快一点,所以这是我目前使用它的唯一原因)

(此外,我的 User 列实际上是 unicode 而不是 int,这对于快速比较可能会有问题)

最佳答案

我的想法与 Andy 相同,只是添加了 groupby,我认为这是对 Andy 的回答的补充。每当您执行 diffshift 时,添加 groupby 只会产生将 NaN 放在第一行的效果。 (请注意,这并不是试图给出确切的答案,只是勾勒出一些基本技术。)

df['time_diff'] = df.groupby('User')['Time'].diff()

df['Col1_0'] = df['Col1'].apply( lambda x: x[0] )

df['Col1_0_prev'] = df.groupby('User')['Col1_0'].shift()

User Time Col1 time_diff Col1_0 Col1_0_prev
0 1 6 [cat, dog, goat] NaN cat NaN
1 1 6 [cat, sheep] 0 cat cat
2 1 12 [sheep, goat] 6 sheep cat
3 2 3 [cat, lion] NaN cat NaN
4 2 5 [fish, goat, lemur] 2 fish cat
5 3 9 [cat, dog] NaN cat NaN
6 4 4 [dog, goat] NaN dog NaN
7 4 11 [cat] 7 cat dog

作为 Andy 关于存储对象的观点的后续,请注意我在这里所做的是提取列表列的第一个元素(并且还添加了一个移位版本)。这样做你只需要做一次昂贵的提取,然后就可以坚持标准的 pandas 方法。

关于python - 将 Pandas 数据框中的行和上一行与数百万行进行比较的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29446844/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com