【问题标题】:More “Pythonian” way to perform a nested loop through an array?通过数组执行嵌套循环的更多“Pythonian”方式?
【发布时间】:2020-10-24 03:08:13
【问题描述】:

下面的代码尝试解决以下任务:“找出任何 5 天滚动窗口,超过 1000 天的最大价格变化”。

我所说的“任何 5 天滚动窗口”不仅仅指“t_i + 5”,而是“t_i + j”,其中“i”从 1 到 1000 不等,“j”从 1 到5.

我曾尝试使用 Numpy 原生函数,但最终还是使用“for-loop”进行内部迭代。代码如下:

prices = npr.random([1000,1])*1000

max_array = np.zeros([(prices.size-5),1])
for index, elem in np.ndenumerate(prices[:-5,:]):
    local_max = 0.0
    for i in range(1,6,1):
        price_return = prices[(index[0] + i),0] / elem
        local_max = max(local_max, price_return)
    max_array[index[0]] = local_max
global_max = np.amax(max_array)

我能否以某种方式消除内部 for 循环并使用 Numpy 向量化(不知何故)?

另外,我不太喜欢使用“index[0]”从通过调用返回到变量“index”的元组对象中提取当前循环的实际索引:

for index, elem in np.ndenumerate(prices[:-5,:]):

这也可以改进吗?

【问题讨论】:

  • “找出任何 5 天滚动窗口内的最大价格变化,超过 1000 天”。如果你明确地寻找一个 5 天的窗口,你为什么需要内部循环呢?您只对每次窗口迭代的 min 和 max 之间的最大差异感兴趣。检查1-4天也没有好处,结果会一样
  • 我不认为结果会是一样的。任何 5 天滚动窗口内的最大变化不一定来自 5 天窗口中的第一天和最后一天。我对任意 5 天窗口内任意两天之间可能发生的最大变化感兴趣。
  • 好的,我不清楚更改必须在连续两天内

标签: python numpy


【解决方案1】:

使用 pandas 滚动窗口获取最小值和最大值

允许在没有 for 循环的情况下进行计算

灵感来自Max in a sliding window in NumPy array

import pandas as pd
import numpy as np

# Generate Data
prices = np.random.random([1000,1])*1000
prices = prices.flatten()

# Pandas rolling window (max in 5 day period)
# Convert series back to numpy array
maxs = pd.Series(prices).rolling(5).max().dropna().to_numpy()

# Pandas rolling window (min in 5 day period)
# Convert series back to numpy array
mins = pd.Series(prices).rolling(5).min().dropna().to_numpy()

# Numpy subtraction to find max and min differnce
delta = maxs - mins

结果(显示前 10 个元素)

print('prices: ', prices[:10])
print('maxs: ', maxs[:10])
print('mins: ', mins[:10])
print('max-change: ', delta[:10])

输出(前 10 个元素)

prices:  [416.67356904 244.29395291 325.50608035 102.67426207 794.36067353
 318.22836941 113.48811096 898.87130071 303.06297351 285.80963998]
maxs:  [794.36067353 794.36067353 794.36067353 898.87130071 898.87130071
 898.87130071 898.87130071 898.87130071 828.87148828 828.87148828]
mins:  [102.67426207 102.67426207 102.67426207 102.67426207 113.48811096
 113.48811096 113.48811096 285.80963998 285.80963998 106.4036413 ]
max-change:  [691.68641146 691.68641146 691.68641146 796.19703863 785.38318975
 785.38318975 785.38318975 613.06166073 543.06184831 722.46784698]

【讨论】:

  • 非常感谢。因此,Python 中的高效编码似乎归结为(除其他考虑因素外)有意识地为特定任务选择最合适的库?我觉得这有点令人沮丧,因为在 C 类型语言中,学习如何有效地使用循环足以解决这类问题。在 Python 中,学习每个库几乎就像学习一种新的编码语言本身......所以说真的,学习高效的 Python 归结为学习特定的库。
  • @JanStuller--我用我当前答案的灵感来源更新了我的答案,以展示如何让它不那么令人沮丧。查看stackoverflow tag count,我们看到Python 在stackoverflow 的问答中名列前三。所以,我发现最好的方法是先看看以前是否解决过类似的问题。然后,这将为我指出库中库和函数的最佳选择。
  • 再次感谢您。顺便说一句,再看一遍,您建议的方法仅返回滚动 5 天窗口内的最大值。然而,我对任意五天滚动窗口任意两天之间的最大差异感兴趣。所以仍然需要在所有 5 天滚动窗口内从“1”到“5”的内部循环。
  • @JanStuller——让我理解一下:如果价格 = [6, 2, 3, 4, 5, 1]。然后使用 5 天的滚动窗口,maxs = [6, 5] 和 min = [2, 1] 会不会,所以 max-change = [4, 4]?它是否正确?如果是这样,这就是答案的作用。如果不是,您能解释一下 maxs、mins 和 max-change 应该是什么吗?
  • 你是对的。我现在看到您的代码完成了这项工作!聪明的做法,我很喜欢。
猜你喜欢
  • 2015-07-09
  • 1970-01-01
  • 1970-01-01
  • 2015-06-05
  • 1970-01-01
  • 2013-07-28
  • 1970-01-01
  • 1970-01-01
  • 2020-05-01
相关资源
最近更新 更多