Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用不带for循环的数组元素进行运算_Python_Arrays_Python 3.x_Numpy_Optimization - Fatal编程技术网

Python 使用不带for循环的数组元素进行运算

Python 使用不带for循环的数组元素进行运算,python,arrays,python-3.x,numpy,optimization,Python,Arrays,Python 3.x,Numpy,Optimization,我有一个问题,需要取数组中的一个元素,分别求这个元素和索引较高的元素的和。我用for循环完成了这项工作,如: sumtot = np.array([]) for j in range(0,len(matpos)-1): sum = matpos[j] + matpos[j+1:] sumtot = np.append(sumtot, sum) 但是这需要大量的计算时间,因为数组matpos是一个非常大的数组,所以我想如果没有for循环,是否有办法做到这一点 这方面的一个简单示例

我有一个问题,需要取数组中的一个元素,分别求这个元素和索引较高的元素的和。我用for循环完成了这项工作,如:

sumtot = np.array([])
for j in range(0,len(matpos)-1):
    sum = matpos[j] + matpos[j+1:]
    sumtot = np.append(sumtot, sum)
但是这需要大量的计算时间,因为数组
matpos
是一个非常大的数组,所以我想如果没有
for
循环,是否有办法做到这一点

这方面的一个简单示例是:

-输入:

matpos = np.array([0, 1, 2, 3])
-输出

sumtot = np.array([1, 2, 3, 3, 4, 5])
这是
[0+1,0+2,0+3,1+2,1+3,2+3]


非常感谢大家

要获得所需的数组,可以使用类似的方法进行一些额外的操作:

r, c = np.triu_indices(len(matpos), 1)
totsum = matpos[r] + matpos[c]
这可能是你能看到的最清晰的了。如果需要一行,可以堆叠索引并将结果相加:

totsum = matpos[np.stack(np.triu_indices(len(matpos), 1))].sum(0)
请注意,术语汇总如下:

 [matpos[0], matpos[0], matpos[0], ...] + [matpos[1], matpos[2], matpos[3], ...]
 [matpos[1], matpos[1], ...] + [matpos[2], matpos[3], ...]
 [matpos[2], ...] + [matpos[3], ...]
所选索引和重复次数与
triu_索引
的结果完全对应(列减1),该结果返回矩阵上三角形的索引

另一种提法:

r, c = np.triu_indices(len(matpos) - 1)
totsum = matpos[r] + matpos[c + 1]


您真的应该包含一个示例运行—这样我们就可以看到您的代码生成了什么,而无需自己运行它

In [85]: matpos = np.arange(10)
In [86]: sumtot = np.array([])
    ...: for j in range(0,len(matpos)-1):
    ...:     sum = matpos[j] + matpos[j+1:]
    ...:     sumtot = np.append(sumtot, sum)
    ...: 
In [87]: sumtot
Out[87]: 
array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.,  3.,  4.,  5.,  6.,
        7.,  8.,  9., 10.,  5.,  6.,  7.,  8.,  9., 10., 11.,  7.,  8.,
        9., 10., 11., 12.,  9., 10., 11., 12., 13., 11., 12., 13., 14.,
       13., 14., 15., 15., 16., 17.])
但这并不是特别有教育意义。此外,
np.append
比list append慢

因此,让我们使用列表:

In [88]: sumtot = []
    ...: for j in range(0,len(matpos)-1):
    ...:     sum = matpos[j] + matpos[j+1:]
    ...:     sumtot.append(sum)
    ...: 
    ...: 
In [89]: sumtot
Out[89]: 
[array([1, 2, 3, 4, 5, 6, 7, 8, 9]),
 array([ 3,  4,  5,  6,  7,  8,  9, 10]),
 array([ 5,  6,  7,  8,  9, 10, 11]),
 array([ 7,  8,  9, 10, 11, 12]),
 array([ 9, 10, 11, 12, 13]),
 array([11, 12, 13, 14]),
 array([13, 14, 15]),
 array([15, 16]),
 array([17])]
这可以更好地了解你在做什么——并不是说它看起来特别合乎逻辑:)

或者,要获取平面列表,请使用扩展:

In [90]: sumtot = []
    ...: for j in range(0,len(matpos)-1):
    ...:     sum = matpos[j] + matpos[j+1:]
    ...:     sumtot.extend(sum)
    ...: 
In [91]: sumtot
Out[91]: 
[1,
 2,
 3,
 ...
 16,
 17]
或者为了更漂亮的展示:

In [92]: np.array(sumtot)
Out[92]: 
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9,  3,  4,  5,  6,  7,  8,  9, 10,
        5,  6,  7,  8,  9, 10, 11,  7,  8,  9, 10, 11, 12,  9, 10, 11, 12,
       13, 11, 12, 13, 14, 13, 14, 15, 15, 16, 17])
我怀疑这个列表扩展版本是我们能得到的最好的版本。[89]中不完整的列表表明,“纯”numpy解决方案不太可能,或者最多是复杂的

编辑 用你的新例子:

In [93]: matpos = np.array([0, 1, 2, 3])
...
In [96]: sumtot = []
    ...: for j in range(0,len(matpos)-1):
    ...:     sum = matpos[j] + matpos[j+1:]
    ...:     sumtot.append(sum)
    ...: 
    ...: 
In [97]: sumtot
Out[97]: [array([1, 2, 3]), array([3, 4]), array([5])]
使用
triu
: 另一个答案是使用
triu

让我们来体验一下:

In [98]: matpos[:,None]+matpos
Out[98]: 
array([[0, 1, 2, 3],
       [1, 2, 3, 4],
       [2, 3, 4, 5],
       [3, 4, 5, 6]])
In [100]: np.tril(__,-1)
Out[100]: 
array([[0, 0, 0, 0],
       [1, 0, 0, 0],
       [2, 3, 0, 0],
       [3, 4, 5, 0]])
对于更大的例子:

In [101]: matpos = np.arange(10)
In [102]: matpos[:,None]+matpos
Out[102]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10],
       [ 2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
       [ 3,  4,  5,  6,  7,  8,  9, 10, 11, 12],
       [ 4,  5,  6,  7,  8,  9, 10, 11, 12, 13],
       [ 5,  6,  7,  8,  9, 10, 11, 12, 13, 14],
       [ 6,  7,  8,  9, 10, 11, 12, 13, 14, 15],
       [ 7,  8,  9, 10, 11, 12, 13, 14, 15, 16],
       [ 8,  9, 10, 11, 12, 13, 14, 15, 16, 17],
       [ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]])
In [103]: np.tril(_,-1)
Out[103]: 
array([[ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 1,  0,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 2,  3,  0,  0,  0,  0,  0,  0,  0,  0],
       [ 3,  4,  5,  0,  0,  0,  0,  0,  0,  0],
       [ 4,  5,  6,  7,  0,  0,  0,  0,  0,  0],
       [ 5,  6,  7,  8,  9,  0,  0,  0,  0,  0],
       [ 6,  7,  8,  9, 10, 11,  0,  0,  0,  0],
       [ 7,  8,  9, 10, 11, 12, 13,  0,  0,  0],
       [ 8,  9, 10, 11, 12, 13, 14, 15,  0,  0],
       [ 9, 10, 11, 12, 13, 14, 15, 16, 17,  0]])
所以非零值匹配

并使用
triu_索引
提取值:

In [112]: idx = np.triu_indices_from(Out[102],1)
In [113]: Out[102][idx]
Out[113]: 
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9,  3,  4,  5,  6,  7,  8,  9, 10,
        5,  6,  7,  8,  9, 10, 11,  7,  8,  9, 10, 11, 12,  9, 10, 11, 12,
       13, 11, 12, 13, 14, 13, 14, 15, 15, 16, 17])

循环的意义是什么?您没有累积结果,因此您放弃了早期迭代的所有总和。很抱歉,我没有添加代码的这一部分,我必须累积结果,让我编辑它。非常感谢。请显示一个示例输入和输出…看起来像反向数组上的
np.cumsum
。或者与列表一起使用
itertools.accumulate
(同样在反向列表上)。@hpaulj。我开始写这篇文章,但OP实际上并不是对文章的各个部分进行总结array@MadPhysicist,你说得对:)
In [112]: idx = np.triu_indices_from(Out[102],1)
In [113]: Out[102][idx]
Out[113]: 
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9,  3,  4,  5,  6,  7,  8,  9, 10,
        5,  6,  7,  8,  9, 10, 11,  7,  8,  9, 10, 11, 12,  9, 10, 11, 12,
       13, 11, 12, 13, 14, 13, 14, 15, 15, 16, 17])