如果不逐行遍历数据框,这需要很长时间,我如何检查多行是不是都满足条件?

Posted

技术标签:

【中文标题】如果不逐行遍历数据框,这需要很长时间,我如何检查多行是不是都满足条件?【英文标题】:Without iterating row by row through a dataframe, which takes ages, how can I check that a number of rows all meet a condition?如果不逐行遍历数据框,这需要很长时间,我如何检查多行是否都满足条件? 【发布时间】:2021-09-26 02:53:29 【问题描述】:

我想做以下事情,但显然我意识到这种迭代方法对于大型DataFrames非常慢,还有什么其他解决方案可以解决这个问题?:

for i in range(len(df)):
    for n in range(1001):
        if df["Close"][(i+n)] > df["MA"][i+n]:
            df["Strategy 1"][i] = "Buy"

我希望上面的代码做的是:

Sub in n from 0 to 1,000 到第 3 行,i 为 0,然后如果第 3 行中的条件对范围内的每个 n 成立0 到 1,000 则继续执行第 4 行的操作。

在此之后,它需要 i of 1,然后将 n 从 0 到 1,000 放入第 3 行,如果该条件适用于该范围内的所有 n,则它将执行第 4 行。

在此之后,它需要 i of 2,然后将 n 从 0 到 1,000 放入第 3 行,如果条件适用于该范围内的所有 n,则它将执行第 4 行。

在此之后,它需要 i of 3,然后将 n 从 0 到 1,000 放入第 3 行,如果该条件适用于该范围内的所有 n,则它将执行第 4 行。

... ...

在此之后,它将采用 i of len(df) 然后将 n 从 0 到 1,000 放入第 3 行,如果条件适用于所有 n该范围然后它将执行第 4 行。

无论上面提供的代码是否符合我的预期,是否有更快的方法来计算非常大的多 GB 数据帧?

【问题讨论】:

【参考方案1】:

首先,让我说明我是如何理解您的规则的。据我所知,只有当有 1000 个连续案例 MA 大于该时间之前的 Close 时,您才试图在 df 的“策略 1”列中获得“买入”值。我认为您只需在比较中使用滚动总和即可完成此操作:

import pandas as pd
import numpy as np

# build some repeatable sample data
np.random.seed(1)
df = pd.DataFrame('close': np.cumsum(np.random.randn(10000)))
df['MA'] = df['close'].rolling(1000).mean()

# Apply strategy
npoints = 1000

df['Strategy 1'] = float('nan')
buypoints = (df['MA'] > df['close']).rolling(npoints).sum() == npoints
df.loc[buypoints, "Strategy 1"] = "Buy"

# just for visualisation show where the Buys would be
df['Buypoints'] = buypoints*10
df.plot()

结果是这样的(使用相同的种子,它在您的机器上也应该看起来一样)

【讨论】:

这绝对是魔法。我仍然需要弄清楚 buypoints = (df['close'] > df['MA']).rolling(npoints).sum() == npoints 行是如何工作的,它似乎完全符合我的需要,但是我只是在概念上还不太明白。感谢您的回答,唯一的事情是我想做close>ma not ma>close,但除了你把它砸了,谢谢! @MoonBoi9001 原因是您评估条件,即真或假。 rolling(npoints).sum() 然后计算它在窗口中的 多少 次 True,因为 True 的行为类似于 1,而 False 的行为类似于 0。然后您执行== npoints 以查找整个窗口为 True 的位置。现在这是一个布尔数组,您可以使用它来索引原始数据帧以访问它为 True 的点。 很好的解释,将您标记为已接受的答案,真的帮助了我谢谢!【参考方案2】:

使用 .apply 函数会更快。举个一般的例子……

import pandas as pd

# only required to create the test dataframe in this example
import numpy as np

# create a dataframe for testing using the numpy import above
df = pd.DataFrame(np.random.randint(100,size=(10, )),columns=['A'])

# create a new column based on column 'A' but moving the column 'across and up'
df['NextRow'] = df['A'].shift(-1)

# create a function to do something, anything, and return that thing
def doMyThingINeedToDo(num, numNext):
#     'num' is going to be the value of whatever is in column 'A' per row 
#     as the .apply function runs below and 'numNext' is plus one.
    if num >= 50 and numNext >= 75:
        return 'Yes'
    else:
        return '...No...'

# create a new column called 'NewColumnName' based on the existing column 'A' and apply the
# function above, whatever it does, to the frame per row.
df['NewColumnName'] = df.apply(lambda row : doMyThingINeedToDo(row['A'], row['NextRow']), axis = 1)

# output the frame and notice the new column
print(df)

输出:

    A  NextRow NewColumnName
0  67     84.0           Yes
1  84     33.0      ...No...
2  33     59.0      ...No...
3  59     85.0           Yes
4  85     39.0      ...No...
5  39     81.0      ...No...
6  81     76.0           Yes
7  76     83.0           Yes
8  83     60.0      ...No...
9  60      NaN      ...No...

主要的一点是,您可以将每行的具体操作分开并将其包含在一个函数中(可以根据需要进行调整和更新),并在需要时为框架上的所有行调用该函数。

【讨论】:

因此,如果我想检查 A 列第 0 行和 A 列第 1 行中包含的元素是否大于 1,然后将它们放入 newcolumnname 第 0 行中,我将如何这样做? 我已经更新了您可以实现它的方法的答案。 感谢您的回答,这是一个很好的解决方案,但也意味着我已经数千兆字节的数据库需要变得更大,我正在使用 140 万行和 1000 多列来实现此解决方案我需要再添加 2,500 多列,在这些列的每一行中填充一个元素,这样我的数据库就会增长到 25GB 以上,这不是我现在急于让这种情况发生的事情。【参考方案3】:

您只需使用关闭的数据即可完成您正在尝试的事情。通过矢量化即时计算 MA 和 1000 个条件。也许试试这个:

import numpy as np

ma_window = 1000 
n = 1000 

df['Strategy 1'] = \
    np.where( \
        (df['close'] > df['close'].rolling(window=ma_window).mean()).rolling(window=n).mean() == 1, \
             'buy','')
         

试试这个,看看它是否适合你。

【讨论】:

【参考方案4】:

迭代是 Pandas 的最后手段。

您正在寻找的解决方案来自 numpy:

import numpy as np
df["Strategy 1"] = np.where(df["Close"] > df["MA"], "Buy", df["Strategy 1"])

【讨论】:

不确定我的问题是否清楚,但我试图检查的不仅仅是 df["Close"][i] > df["MA"][i] df["收盘"][i+1] > df["MA"][i+1], df["收盘"][i+2] > df["MA"][i+2], df[ "关闭"][i+3] > df["MA"][i+3], ... , df["关闭"][i+n] > df["MA"][i+n] 然后当且仅当所有这些都成立时,然后执行 df["Strategy 1"][i] = "Buy" @MoonBoi9001 这就是答案的作用,也许这有帮助:numpy.org/doc/stable/user/basics.broadcasting.html,还是我误解了,你的逻辑有跨行依赖?一个明确的预期输入和预期输出示例将非常清楚地说明这个问题。

以上是关于如果不逐行遍历数据框,这需要很长时间,我如何检查多行是不是都满足条件?的主要内容,如果未能解决你的问题,请参考以下文章

Pyspark:保存数据框需要很长时间

PayPal API 需要很长时间才能响应

MySQL 查询返回 JSON 数据需要很长时间

Python: Pandas - 嵌套循环需要很长时间才能完成。如何加快速度?

如何阻止用户等待很长时间才能获得位置修复?

XCode bot需要很长时间才能集成