繁体   English   中英

当平均值高于另一个列表中的相同条目时,将列表中的无替换为最后 3 个非无条目的平均值

[英]Replace None in list with average of last 3 non-None entries when the average is above the same entry in another list

我有两个列表:

dataa = [11, 18, 84, 51, 82, 1, 19, 45, 83, 22]
datab = [1, None, 40, 45, None, None, 23, 24, None, None]

对于前 3 个条目大于数据条目的任何实例,我需要替换 datab 中的所有 None(请参见下面的演练示例)。 忽略没有 3 个先前非无条目的条目以进行平均以与 dataa 进行比较。

我的第一次尝试是这样的:

for i in range(len(dataa)):
        if (datab[i] == None):
                a = (datab[i-3]+datab[i-2]+datab[i-1])/3
                if ((datab[i-3]+datab[i-2]+datab[i-1])/3 > dataa[i]):
                        datab[i] = dataa[i]

在前 3 个中有一个为 None 的情况下,尝试计算前三个的平均值会出错。 我试图保持总计,但其中一些失败了。

c = 0;
a = 0;
for i in range(len(dataa)):
        c = c + 1
        if (datab[i] == None):
                if (a > dataa[i]):
                        datab[i] = a
        else:
                if (c > 2):
                        a = (a * 3 + datab[i])/3

这也没有按预期工作。

从这个样本数据中,我预计:

  • 条目 1、2 和 3 没有平均值,因此保留原样。
  • 条目 5 在 datab 中为 None,在 dataa 中为 82。 由于(1+40+45)/3 = 28.66我们也保持原样。
  • 条目 6 在 datab 中为 None,在 dataa 中为 1。 3 个先前的非 None 平均值更大 ( 28.66 > 1 ),因此设置为 28.66 平均值。
  • 条目 9 为 None,但(28.66+23+24)/3 = 25.22不大于 83,因此保留原样。
  • 条目 10 为 None 并且 3 个先前的非 None 平均值更大( 25.22>22 ),因此将其设置为 25.22 平均值。

正确的预期 output:

[1, None, 40, 45, None, 28.66, 23, 24, None, 25.22]

让我们使用collections.deque来跟踪要平均的数字 window,因为从deque顶部弹出比从列表顶部弹出便宜。

感谢@ShadowRanger 指出dequemaxlen特性,它允许我们 append 一个元素,如果需要,deque 会自动弹出左边的元素。

from collections import deque

dataa = [11, 18, 84, 51, 82, 1, 19, 45, 83, 22]
datab = [1, None, 40, 45, None, None, 23, 24, None, None]

result = []

moving_avg = 0
sliding_window = deque(maxlen=3)

# Iterate over the two lists simultaneously
for a, b in zip(dataa, datab):
    # If b already has a value
    # Or the window has less than three items
    # Or the average is less than the element of dataa
    if b is not None or len(sliding_window) < 3 or moving_avg < a:
        # Append the element of datab to result
        result.append(b)
    else:
        # Else, append the moving average
        result.append(moving_avg)

    # If the value we just appended to our result is not None
    # Then append it to the sliding window
    if result[-1] is not None:
        sliding_window.append(result[-1])
    
    # Recalculate moving average
    moving_avg = sum(sliding_window) / len(sliding_window)
        
        
print(result) 
# [1, None, 40, 45, None, 28.666666666666668, 23, 24, None, 25.222222222222225]

您可以通过跟踪从双端队列中弹出的元素并使用它来计算移动平均值来节省一些计算时间,但是对于大小为 3 的双端队列来说,这无论如何都不是什么大问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM