Python 使用不带for循环的数组元素进行运算
我有一个问题,需要取数组中的一个元素,分别求这个元素和索引较高的元素的和。我用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循环,是否有办法做到这一点 这方面的一个简单示例
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])