有没有一种方法可以向量化此pandas apply方法,以使代码运行更快?

时间:2020-06-16 09:26:38

标签: python pandas numpy dataframe

当前运行约220K行需要40至50分钟

shop    timestamp   flag
10061   1577525275  NaN
10061   1577534732  NaN
10061   1577741715  NaN
10061   1577741800  NaN
10084   1577405286  NaN
def foo(row):
    criteria = (pd.isnull(df2.flag)) & (df.shop==row.shop) & (abs(df.timestamp-row.timestamp) <= 3600)
    df2.loc[criteria, 'flag'] = 1
df2 = df.copy()
df2.apply(foo, axis=1)

我正在做的是df2中的每一行,我正在对照主df进行检查,看看是否在同一家商店中,在小时内还有哪些其他行具有时间戳,并将标志设置为1。 numpy向量使运行速度更快的方法?

预期输出:

shop    timestamp   flag
10061   1577525275  NaN
10061   1577534732  NaN
10061   1577741715  1
10061   1577741800  1
10084   1577405286  NaN

2 个答案:

答案 0 :(得分:1)

要更快地完成任务,请定义以下功能:

def newFlag(grp):
    tt = grp.timestamp
    ind = np.nonzero(np.triu(np.absolute(tt[np.newaxis, :] - tt[:, np.newaxis]) <= 3600, 1))
    tbl = grp.flag.values
    tbl[np.concatenate(ind)] = 1
    return pd.Series(np.where(np.isnan(grp.flag), tbl, grp.flag), index=grp.index)

然后应用它,将结果保存在 flag 列中:

df['flag'] = df.groupby('shop').apply(newFlag).reset_index(level=0, drop=True)

此解决方案的速度基于 shop 的分组,因此您不必 比较有关不同商店的行。

另一个与速度有关的重要因素是使用 Numpy 函数, 它的运行速度比 Pandas 快得多。

要完全理解所有详细信息,请为选定的组逐步运行此代码 行(针对特定的 shop ),然后查看结果。

答案 1 :(得分:0)

您需要按商店对数据框进行分组,然后按时间戳对每个组进行排序,最后只检查上一行和下一行:

print(df)
    shop   timestamp
0  10061  1577525275
1  10061  1577534732
2  10061  1577741715
3  10061  1577741800
4  10084  1577405286


def have_similar(df):
    df = df.sort_values('timestamp')
    df = df.assign(
        flag = (df.timestamp - df.timestamp.shift(1) < 3600) |
               (df.timestamp.shift(-1) - df.timestamp < 3600)
    )
    return df

result = df.groupby('shop').apply(have_similar).reset_index(drop=True)


print(result)
    shop   timestamp   flag
0  10061  1577525275  False
1  10061  1577534732  False
2  10061  1577741715   True
3  10061  1577741800   True
4  10084  1577405286  False