【发布时间】:2020-05-01 13:43:21
【问题描述】:
我正在从 R 切换到 Python。不幸的是,我发现虽然某些结构在 R 中几乎可以立即运行,但在 Python 中却需要几秒钟(甚至几分钟)。阅读后,我发现在 pandas 中强烈建议不要使用 for 循环,建议使用其他替代方法,例如矢量化和应用。
在此示例代码中:从从最小值到最大值排序的一列值中,保留在长度为“200”的间隙之后出现的所有值。
import numpy as np
import pandas as pd
#Let's create the sample data. It consists of a column with random sorted values, and an extra True/False column, where we will flag the values we want
series = np.random.uniform(1,1000000,100000)
test = [True]*100000
data = pd.DataFrame({'series' : series, 'test':test })
data.sort_values(by=['series'], inplace=True)
#Loop to get rid of the next values that fall within the '200' threshold after the first next valid value
for i in data['series']:
if data.loc[data['series'] == i,'test'].item() == True:
data.loc[(data['series'] > i) & (data['series'] <= i+200 ) ,'test' ] = False
#Finally, let's keep the first values after any'200' threshold
data = data.loc[data['test']==True , 'series']
是否可以将其转换为函数、矢量化、应用或除“for”循环之外的任何其他结构以使其几乎立即运行?
【问题讨论】:
-
对于这种动态,
for循环似乎是不可避免的。 -
注意,pandas 中的
.apply不会比循环快,除非您在列上应用矢量化函数。 -
我认为问题出在
data['series'] == i,这是一个 O(n) 操作,data['series'] > i和data['series'] <= i+200也是 O(n)。所以你有一个外部循环(for i in data['series']),它将运行 O(n) 次,并且在循环内你正在执行 O(n) 操作。所以你的算法是O(n ^ 2)。由于输入的大小为 100,000,因此您将执行大约 10^10 次操作,这很棘手。 -
补充我上面的评论:我猜 R 中的相应算法在排序后只是 O(n),所以它可能运行得更快。 (O(n) 算法将遍历列的所有索引
i,并检查 i 和 i+1 处的值之间的差异)