[英]Method to avoid this nested for-loop
此代码是否需要嵌套的 for 循环,或者是否有更有效的解决方法?
这是一个简化版本,它在由 1 到 1000 的 20 个随机整数组成的数据集中搜索连续的重叠间隔。它运行 1-100 的误差值,通过从 20 个随机整数中添加/减去它们来创建间隔。
例子:
输入假设数据帧的大小为 10 而不是 20:
df = [433, 3, 4, 5, 6, 7, 378, 87, 0, 500]
for 循环中 error = 1 的输出:
重叠 = {0:[[1, 2, 3, 4, 5]]}
def find_overlap(df, error):
"""
df: dataframe with random 20 integers from 1-1000
error: used to create the interval by +/- to each value in the dataframe
returns: list of list of indexes overlapping
"""
# add the interval to the dataframe as columns of minimum and maximum
df["min"] = df["x"] - error
df["max"] = df["x"] + error
# overlaps stores lists of indexes that overlap
overlaps = []
# fill in data for start
temporary = [0]
minimum = df["min"].iloc[0]
maximum = df["min"].iloc[0]
# iterates through the dataframe checking for overlap between successive intervals
for index , row in df.iterrows():
current_min = row["min"]
current_max = row["max"]
# yes overlap
if (current_min <= maximum) and (current_max >= minimum):
temporary.append(index)
if current_min > minimum:
minimum = current_min
if current_max < maximum:
maximum = current_max
continue
# no overlap - also check for 5 successive overlaps
if len(temporary) >= 5:
overlaps.append(temporary)
temporary = [index]
minimum = current_min
maximum = current_max
return overlaps
# creates dataframe with 20 random integers from 1 to 1000
df = pd.DataFrame(np.random.randint(1, 1000, 20), columns=["x"])
overlaps = {}
for error in range(0,100):
lst = find_overlap(df, error)
if len(lst):
overlaps[error] = lst
print(overlaps)
所以,从我从你的代码中了解到的......你正在寻找:
x
所有值之间的差值。error
,其中error
从范围[0, 100)
假设我的解释是正确的......你实际上可以将其矢量化并避免 for 循环,就像你的直觉让你相信一样。 最终,如果我的解释不正确,这至少应该为您创建所需代码的矢量化版本提供一个不错的开始。 🙂
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randint(1, 1000, 20), columns=["x"])
overlaps = {}
for margin in range(0, 100):
diffs = np.abs(df["x"].values - np.roll(df["x"], margin))
# np.convolve is analogous to a sliding window sum
quint = np.convolve(diffs == margin, np.ones(5), "valid")
index = np.nonzero(quint == 5)[0]
if index.size > 0:
overlaps[margin] = [list(range(i, i + 5)) for i in index]
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randint(1, 1000, 20), columns=["x"])
overlaps = {}
for margin in range(0, 100):
diffs = np.abs(df["x"].values - np.roll(df["x"], margin))
index = np.nonzero(diff == margin)[0]
if idx.size > 0:
overlaps[margin] = idx
如果您不熟悉numpy
, .size
会为您提供ndarray
的总大小。 (所以形状为(10, 20, 30)
的 3D 数组的大小为6000
。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.