【问题标题】:Add some values at some range in numpy array?在numpy数组的某个范围内添加一些值?
【发布时间】:2020-02-29 14:58:52
【问题描述】:

我有一个像这样的 numpy 数组

[1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]

现在我有一个二维数组,它告诉开始索引和结束索引以及要求和的值。像这样

[[5, 12, 29] [8, 22, 719]]

我想更快地将这些数字添加到我的初始数组中。

目前我的解决方案是

f= np.zeros(n+1, dtype = int)

# print(rounds)
for elem in rounds:
    print('rounds : ',elem)
    one = elem[0]
    two = elem[1]
    value_add = elem[2]
# for i in range(0,n+1):
    for i in range(one-1,two):
        f[i-1] += value_add
        # print(f)

矩阵太长时速度很慢,还有其他优化方法吗?

第二次迭代尝试优化

将 numpy 导入为 np

f= np.zeros(n+1, dtype = int)

# print(rounds)
new = np.zeros(n+1)
for elem in rounds:
    # prin  t('rounds : ',elem)
    one = elem[0]
    two = elem[1]
    value_add = elem[2]
# for i in range(0,n+1):

    new[one-1:two] += value_add

【问题讨论】:

  • 我对“求和”部分并不完全清楚。我是否正确假设原始数组的元素必须增加一定数量,从第一个索引开始到第二个索引之前结束?也就是说[2, 5, 3]这样的条目会导致原来的变成[1, 2, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
  • 是的,没错

标签: python arrays


【解决方案1】:

您可以创建掩码并使用间接来让 numpy 完成所有工作(即没有任何循环):

import numpy as np
a   = np.array([1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])
iv  = np.array([[5, 12, 29], [8, 22, 719]])

valueMask     = (np.arange(a.size)>=iv[:,0:1]) & (np.arange(a.size)<iv[:,1:2])
valueIndex    = np.max((np.arange(iv.shape[0])+1)[:,None]*valueMask,axis=0)-1
targetMask    = valueIndex>=0
a[targetMask] = iv[valueIndex[targetMask],2]

输出:

print(a)

[  1   2   2   2   2  29  29  29 719 719 719 719 719 719 719 719 719 719  719]

valueMask 变量是a 中位置的真/假矩阵,其中将分配iv 的每个值。

valueIndex 变量将掩码转换为一维数组,指示将在每个位置最后分配iv 值(索引)中的哪一个。对于未更改的位置,它将包含 -1。

targetMask 变量挑选出a 中实际会收到新值的位置,并排除不会更改的位置。它会产生一个真/假的位置掩码,用于间接赋值。

最后一步是使用将要分配的最后一个值(iv 的最高索引)将targetMask 定义的a 中的元素子集与iv 的对应值一起分配。

我希望这将为您提供所需的性能。我测量了将 300 个范围分配给 2000 个项目的数组,并在我的笔记本电脑上得到了 0.0028 秒的时间。

【讨论】:

    【解决方案2】:

    这个怎么样?

    a = np.array([1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])
    instr_array = np.array([[5, 12, 29], [8, 22, 719]])
    
    for start, end, incr in instr_array:
        a[start:end] += incr
    

    【讨论】:

    • 是的,我仍然会因 14 个测试用例中的 8 个而受到时间惩罚。
    • 如果我可以问,这些测试在哪里托管?
    • 在hackerrank平台上。
    猜你喜欢
    • 2012-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    • 2018-12-25
    • 2019-08-31
    相关资源
    最近更新 更多