【问题标题】:Sum slices of consecutive values in a NumPy array对 NumPy 数组中连续值的切片求和
【发布时间】:2015-06-06 03:51:04
【问题描述】:

假设我有一个包含 10 个值的 numpy 数组 a。这里只是一个示例情况,尽管我想对长度为 100 的数组重复相同的操作。

a = np.array([1,2,3,4,5,6,7,8,9,10])

我想将前 5 个值与后 5 个值相加,以此类推,并将它们存储在一个新的空列表中,例如 b

所以b 将包含b = [15,40]

我该怎么做呢?

【问题讨论】:

    标签: python arrays list numpy sum


    【解决方案1】:

    一种方法是使用add ufunc 及其reduceat 方法:

    >>> np.add.reduceat(a, [0,5])
    array([15, 40])
    

    这对切片 a[0:5]a[5:] 求和并返回一个新数组。

    如果你想要一个 Python 列表,你可以在返回的数组上调用 tolist()

    您可以在该方法中使用任何索引列表(并且它们不必均匀分布)。例如,如果您希望每次在长度为 100 的数组上切片 5:

    >>> b = np.arange(100)
    >>> np.add.reduceat(b, range(0, 100, 5))
    array([ 10,  35,  60,  85, 110, 135, 160, 185, 210, 235, 260, 285, 310,
       335, 360, 385, 410, 435, 460, 485])
    

    【讨论】:

    • 但是对于更大的 len = 100 数组,我需要相同的!有没有办法扩展它?
    • 该方法的适应性很强 - 你能澄清一下你想要更大的数组吗?
    • 当我对较大的数组执行此操作时,我只得到两个值!但我需要得到 20 个值,因为我的数组是 len = 100
    • @user3397243:我在回答中添加了一些附加信息。
    【解决方案2】:

    这里(还有)另一种解决方案:

    In [3]: a.reshape((2,5)).sum(axis=1)
    Out[3]: array([15, 40])
    

    将一维数组重塑为两行 5 列并对列求和:

    In [4]: a.reshape((2,5))
    Out[4]: 
    array([[ 1,  2,  3,  4,  5],
           [ 6,  7,  8,  9, 10]])
    

    每行的总和(列项的总和)用axis=1 指定。重塑无需复制数据(也无需修改原始 a),因此高效且快速。

    【讨论】:

    • 您能详细说明一下吗?
    • 但是为此我需要更改每个新数组的形状!
    • 是的:如果数组的长度不同,您需要计算正确的形状以在此处使用:例如要调整大小的形状将是 (n//k, k),对于长度为 n 的数组对长度为 k 的连续块求和,n 最好能被 k 整除。
    • 我更喜欢这个解决方案;没有手动循环,它适用于所有(大多数?)Numpy 函数(sum、mean、...),reduceat 的解决方案不是。
    【解决方案3】:

    试试这个列表理解:

    b = [sum(a[current: current+5]) for current in xrange(0, len(a), 5)]
    

    它一次从列表中取出 5 个切片,将它们相加并构造一个列表。也适用于长度不是 5 的倍数的列表。

    xrange 在 python3+ 中应该是 range

    【讨论】:

    • 这效率不高。在使用 np.array 时,您应该尽可能使用 Numpy API,如此处的其他答案所示。我刚刚开始学习如何使用 Numpy,所以我可能会弄错,但根据经验,如果您使用 for,您可能做错了什么。
    • 我认为完全相反:您应该谨慎使用 numpy(或效率构造而不是一般构造),并且仅在您真正需要的地方使用。在非常特殊的情况下需要效率。不要让他们支配你的代码。
    • 确实你不应该过早地优化你的代码,但是这个问题是关于 Numpy 数组的。鉴于这种情况,答案应该使用 Numpy API。如果有人刚开始使用 Numpy 使用这个答案但正在做图像处理工作怎么办?性能会很差,所以这个答案只会浪费他们的时间而不是帮助他们。
    • “假设”正是导致过早优化的思维类型。我仍然不同意将库 API 用于宿主语言中现成的东西。如果需要在更多上下文中使用此代码怎么办?如果它需要移动到不同的图书馆怎么办?如果它由不熟悉 numpy 的开发人员阅读和维护怎么办?我们可以提出任何假设来支持我们的主张,但我们只知道 OP 的要求。 python中有一个简单的解决方案,任何python程序员都可以理解。
    • Numpy 在某些领域非常普遍,以至于在风格上可能不鼓励使用本机 python 结构。此外,在许多已经使用 numpy 数组的情况下,它们正在处理大型数组,因此 20 倍的加速是值得的。
    【解决方案4】:

    你可以使用

    import numpy as np
    
    a = np.array([1,2,3,4,5,6,7,8,9,10])
    step = 5
    
    for i in range(0,a.shape[0],step):
        print(np.sum(a[i:i+step]))
    

    【讨论】:

    • 这效率不高。使用 np.array 时应尽可能使用 Numpy API
    • @SagieLevy,接受的答案与列表理解做同样的事情,可能值得对此发表评论
    【解决方案5】:

    在您的特定情况下,计算 5 个连续元素的总和:

    a = np.array([1,2,3,4,5,6,7,8,9,10])
    print(a.reshape((-1,5)).sum(axis=1))
    

    一般来说,要对 N 个连续元素执行 numpy 数组操作 oper(例如 meanmax):

    print(a.reshape((-1,N)).oper(axis=1))
    

    注意len(a) 必须能被N 整除。

    【讨论】:

      猜你喜欢
      • 2020-01-15
      • 2023-03-22
      • 2020-04-13
      • 2017-08-09
      • 1970-01-01
      • 2014-11-25
      • 1970-01-01
      • 1970-01-01
      • 2019-09-18
      相关资源
      最近更新 更多