【问题标题】:calculate sum of Nth column of numpy array entry grouped by the indices in first two columns?计算由前两列中的索引分组的numpy数组条目的第N列的总和?
【发布时间】:2020-09-13 13:30:46
【问题描述】:

我想循环跟踪check_matrix,以便代码识别第一个和第二个元素是11 还是12 等?然后对于每个单独的对类,即1,11,22,2,代码应存储在新矩阵中,最后一个元素(在本例中具有索引8)乘以exp(-i*q(check_matrix[k][2:5]-check_matrix[k][5:8])) 的总和,其中@ 987654330@ 是 iota(复数),k 是 check_matrix 上的运行索引,q 是如下定义的向量。所以有 20 个q 向量。

import numpy as np

q= []
for i in np.linspace(0, 10, 20):
    q.append(np.array((0, 0, i)))
q = np.array(q)

check_matrix = np.array([[1, 1, 0, 0, 0, 0,    0,       -0.7977, -0.243293],
                         [1, 1, 0, 0, 0, 0,    0,       1.5954,  0.004567],
                         [1, 2, 0, 0, 0, -1,   0,       0,       1.126557],
                         [2, 1, 0, 0, 0, 0.5,  0.86603, 1.5954,  0.038934],
                         [2, 1, 0, 0, 0, 2,    0,       -0.7977, -0.015192],
                         [2, 2, 0, 0, 0, -0.5, 0.86603, 1.5954,  0.21394]])

这意味着原则上我必须有 20 个形状为 2x2 的矩阵,对应于每个 q 向量。

目前我的代码只给出了一个矩阵,它似乎是最后一个矩阵,即使我在Matrices 中附加。我的代码如下所示,

for i in range(2):
    i = i+1
    for j in range(2):
        j= j +1
        j_list = []
        Matrices = []
        for k in range(len(check_matrix)):
            if check_matrix[k][0] == i and check_matrix[k][1] == j:
                j_list.append(check_matrix[k][8]*np.exp(-1J*np.dot(q,(np.subtract(check_matrix[k][2:5],check_matrix[k][5:8])))))
                j_11 = np.sum(j_list)
                I_matrix[i-1][j-1] = j_11
                Matrices.append(I_matrix)

I_matrix 定义如下:

I_matrix= np.zeros((2,2),dtype=np.complex_)

目前我得到以下输出。

Matrices = [array([[-0.66071446-0.77603624j, -0.29038112+2.34855023j],         [-0.31387562-0.08116629j,  4.2788    +0.j        ]])]

但是,我希望得到一个对应于每个 q 值的矩阵,这意味着在这种情况下总共应该有 20 个矩阵,其中每个 2x2 矩阵元素将包含总和,使得元素属于 1,1 和 1 ,2 和 2,2 以下列方式对

 array([[11., 12.],
       [21., 22.]])

非常感谢您提出的更正建议。提前致谢!

【问题讨论】:

  • 如何得到第一个元素为 (1, 1) (1, 2) 等的矩阵?也许如果您使用更智能的索引/重塑,您就不必以如此复杂的方式检索信息!并且缺少q_1df_matrixI_matrix,请提供所有信息以运行您的代码。
  • 感谢您的友好回复。我做了一些小的改动,这些是只有q,而不是q_1。没有df_matrixI_matrix 现在已经定义好了。
  • 我还是想知道check_matrix是怎么得到的,这里算什么,我觉得没必要这么复杂。
  • 嗯,校验矩阵是数据的一小部分,我从另一个代码中获得的。我打算对我的数据执行傅里叶变换。
  • 你试过我推荐的 3-liner 了吗?

标签: python numpy loops matrix nested


【解决方案1】:

我很确定您可以以更简单的方式解决此问题,但我不能 100% 确定我理解正确,但这里有一些代码可以满足您的需求。如果您有可能检查结果是否有效,我建议您这样做。

import numpy as np

n = 20
q = np.zeros((20, 3))
q[:, -1] = np.linspace(0, 10, n)

check_matrix = np.array([[1, 1, 0, 0, 0, 0,    0,       -0.7977, -0.243293],
                         [1, 1, 0, 0, 0, 0,    0,       1.5954,  0.004567],
                         [1, 2, 0, 0, 0, -1,   0,       0,       1.126557],
                         [2, 1, 0, 0, 0, 0.5,  0.86603, 1.5954,  0.038934],
                         [2, 1, 0, 0, 0, 2,    0,       -0.7977, -0.015192],
                         [2, 2, 0, 0, 0, -0.5, 0.86603, 1.5954,  0.21394]])
check_matrix[:, :2] -= 1  # python indexing is zero based

matrices = np.zeros((n, 2, 2), dtype=np.complex_)

for i in range(2):
    for j in range(2):
        k_list = []
        for k in range(len(check_matrix)):
            if check_matrix[k][0] == i and check_matrix[k][1] == j:
                k_list.append(check_matrix[k][8] *
                              np.exp(-1J * np.dot(q, check_matrix[k][2:5] 
                                                     - check_matrix[k][5:8])))

        matrices[:, i, j] = np.sum(k_list, axis=0)

注意:我更改了您的索引以保持一致 从零开始的索引。


这是另一种方法,我将 k-loop 替换为矢量版本:

for i in range(2):
    for j in range(2):
        k = np.logical_and(check_matrix[:, 0] == i, check_matrix[:, 1] == j)
        temp = np.dot(check_matrix[k, 2:5] - check_matrix[k, 5:8], q[:, :, np.newaxis])[..., 0]
        temp = check_matrix[k, 8:] * np.exp(-1J * temp)
        matrices[:, i, j] = np.sum(temp, axis=0)

【讨论】:

  • 我认为这些是适当存储数据的好建议,但我想知道如何根据每个 q 值查看 20 个矩阵。
  • 非常感谢。我尝试了第一个版本,即没有矢量化版本,我达到了预期的结果。我稍后会尝试第二个版本并会更新。
  • 对不起,我是 stackoverflow 的新手,所以不知道要投票我必须点击那个箭头。我认为将其设置为绿色勾号已经可以了,但请竖起大拇指再次感谢!
【解决方案2】:

3 线解决方案

您在原始标题中要求提供有效的解决方案,那么该解决方案如何避免嵌套循环和 3 行中的 if 语句,因此希望更快?

fac=2*(check_matrix[:,0]-1)+(check_matrix[:,1]-1)
grp=np.split(check_matrix[:,8], np.cumsum(np.unique(fac,return_counts=True)[1])[:-1])
[np.sum(x) for x in grp]

输出:

[-0.23872600000000002, 1.126557, 0.023742000000000003, 0.21394]

它是如何工作的?

我将前两列合并为一个索引,将每一列视为“位”(即基数 2)

fac=2*(check_matrix[:,0]-1)+(check_matrix[:,1]-1)

( 如果您的索引超过 2,您仍然可以使用此技术,但您需要使用不同的基数来组合列。即,如果您的索引从 1 变为 18,则需要将列 0 乘以一个等于或大于 18 而不是 2 的数字。)

所以第一行的结果是

array([0., 0., 1., 2., 2., 3.])

请注意,它假设数据是有序的,一列变化最快,如果不是这种情况,您将需要一个额外的步骤来对索引和原始校验矩阵进行排序。在您的示例中,数据是有序的。

下一步根据索引对数据进行分组,and uses the solution posted here.

np.split(check_matrix[:,8], np.cumsum(np.unique(fac,return_counts=True)[1])[:-1])

[array([-0.243293,  0.004567]), array([1.126557]), array([ 0.038934, -0.015192]), array([0.21394])]

即它根据fac的分组输出check_matrix的第8列

然后最后一行简单地将这些相加......知道前两列如何组合以提供单个索引允许您将结果映射回来。或者,如果需要,您可以简单地将其添加到检查矩阵中作为第 9 列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多