【问题标题】:Pythonic Way to group sections of a list into multiple lists based off value基于值将列表的部分分组为多个列表的 Pythonic 方式
【发布时间】:2021-02-10 01:54:12
【问题描述】:

下面是我制作的图,其中 y 轴 (v) 是列表中包含的值。如您所见,列表值在高值段和低值段之间交替,使得列表看起来像:

li = [0.5,0.49,0.5,..,0.5,0.001,0.001,...,0.001,0.49,0.5,...,0.5,]

我的目标是取高值的六个段中的每一个和低值的六个段中的每一个,然后计算每个段的平均值。为此,我试图将上面的列表分开并将每个段放入自己的列表中,并将每个列表放入相应的高值/低值列表中。大致如下:

high_segments = [[high_values1],[high_values2],[high_values3]]
low_segments  = [[low_values1],[low_values2],[low_values3]]

我一直在尝试构建一个 for 循环来执行此操作,但一直在努力解决如何处理低值组和高值组之间的变化。非常感谢任何建议。

【问题讨论】:

    标签: python list for-loop list-comprehension


    【解决方案1】:

    使用numpy 并按均值分割。

    import numpy as np
    
    li = np.array([
        0.5, 0.49, 0.5,
        0.001, 0.001, 0.001,
        0.49, 0.5, 0.5,
        0, 0.002, 0.01,
    ])
    
    # Split into high/low groups using the mean:
    is_high = li >= li.mean()
    is_low = li < li.mean()
    
    # Determine the groups:
    diff = np.insert(np.diff(is_high), 0, False).astype(np.int)  # array([0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0])
    groups = diff.cumsum()  # array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3])
    
    high_segments = np.array([li[groups==kk] for kk in np.unique(groups[is_high])])
    low_segments = np.array([li[groups==kk] for kk in np.unique(groups[is_low])])
    
    high_segments_mean = high_segments.mean(axis=1)
    low_segments_mean = low_segments.mean(axis=1)
    

    【讨论】:

    • 这看起来很完美!谢谢你。您能否解释一下倒数第二行代码的作用。我对这些 numpy 属性的使用不是很熟悉。比如这里的 insert 和 diff 函数是干什么的?
    • is_high 是 True 和 False 值的数组。您可以使用 np.diff() 找到从高到低的转换位置,反之亦然,它计算数组中每个值与其前一个值之间的差异。取差意味着您最终会在数组中少一个值,因此您需要使用 np.insert() 在索引 0 处插入一个额外的 False 值。然后 diff 数组的累积总和为您提供组。
    【解决方案2】:

    我假设您的输入数组li 是连续的 6 高值和 6 低值,因此该数组有 36 个元素。首先,numpy.reshape 函数创建一个连续的 6 元素子数组。然后,我们可以通过切片选择奇数子数组(图中的高值)和偶数子数组(低值)。通过第二个轴堆叠两个阵列将形成所需的形状。 block_reduce 函数会针对每个块进行计算。

    import numpy as np
    # conda install -c anaconda scikit-image
    from skimage.measure import block_reduce
    
    if __name__ == '__main__':
        li = np.arange(0, 36)
        li = li.reshape(-1, 6)
        high_values = li[::2]
        low_values = li[1::2]
        combined = np.stack((high_values, low_values), axis=1)
        segment_average = block_reduce(combined, block_size=(1,2,6), func=np.mean, cval=np.mean(combined)).flatten()
        print(f"[main] input:\n{li}")
        print(f"[main] high_values:\n{high_values}")
        print(f"[main] low_values:\n{low_values}")
        print(f"[main] combined:\n{combined}")
        print(f"[main] segment average: {segment_average}")
    

    结果:

    [main] input:
    [[ 0  1  2  3  4  5]
     [ 6  7  8  9 10 11]
     [12 13 14 15 16 17]
     [18 19 20 21 22 23]
     [24 25 26 27 28 29]
     [30 31 32 33 34 35]]
    [main] high_values:
    [[ 0  1  2  3  4  5]
     [12 13 14 15 16 17]
     [24 25 26 27 28 29]]
    [main] low_values:
    [[ 6  7  8  9 10 11]
     [18 19 20 21 22 23]
     [30 31 32 33 34 35]]
    [main] combined:
    [[[ 0  1  2  3  4  5]
      [ 6  7  8  9 10 11]]
    
     [[12 13 14 15 16 17]
      [18 19 20 21 22 23]]
    
     [[24 25 26 27 28 29]
      [30 31 32 33 34 35]]]
    [main] segment average: [ 5.5 17.5 29.5]
    

    【讨论】:

    • 如果我的问题不完全清楚,我深表歉意。不幸的是,高连续数字和低连续数字的数量并不一致。每个段中的值数量不同,因此可能是 20 高、23 低、24 高、21 低等
    猜你喜欢
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 2020-09-04
    • 1970-01-01
    • 2012-01-30
    • 2019-05-18
    • 1970-01-01
    • 2019-03-14
    相关资源
    最近更新 更多