如何在python中将数组转换为数组列表

时间:2015-04-01 01:15:11

标签: python arrays numpy

来自这个数组

s = np.array([[35788, 41715, ... 34964], 
          [5047, 23529, ... 5165], 
          [12104, 33899, ... 11914], 
          [3646, 21031, ... 3814], 
          [8704, 7906, ... 8705]])

我有这样的循环

end =[]
for i in range(len(s)):
    for j in range(i, len(s)):
        out = mahalanobis(s[i], s[j], invcov)       
        end.append(out)
print end

我接受输出:

[0.0, 12.99, 5.85, 10.22, 3.95, 0.0, 5.12, 3.45, 4.10, 0.0, 5.05, 8.10, 0.0, 15.45, 0.0]

但我希望输出如下:

[[0.0, 12.99, 5.85, 10.22, 3.95], 
[12.99, 0.0, 5.12, 3.45, 4.10], 
[5.85, 5.12, 0.0, 5.05, 8.10], 
[10.22, 3.45, 5.05, 0.0, 15.45], 
[3.95, 4.10, 8.10, 15.45, 0.0]]

5 个答案:

答案 0 :(得分:6)

您需要以至少两种方式循环:

end =[]
for s1 in s:
    end.append([mahalanobis(s1, s2, invcov) for s2 in s])

最重要的是内圈需要再次在整个s上,否则你永远不会得到一个正方形而是1 + 2 + ... + len(s)项(在这种情况下为15 len(s)是5)。

接下来,内部循环必须包含在列表中,因为您需要列表列表。

不太重要但很好:我已经将内循环改为列表理解;并且我已经将两个循环更改为直接在s上,因为我们没有理由重复循环索引的间接,然后使用这些索引来获取s项目关心关于。

所以我总共进行了四次修改,但前两个是你真正需要得到你想要的结果,另外两个是很好的改进: - )。

答案 1 :(得分:3)

鉴于列表,

end = [0.0, 12.99, 5.85, 10.22, 3.95, 0.0, 5.12, 3.45, 4.10, 0.0, 5.05, 8.10, 0.0, 15.45, 0.0]

您可以使用

构建所需的二维数组
import numpy as np
result = np.zeros((s.shape[0],)*2)               # 1
result[np.triu_indices(s.shape[0], 0)] = end     # 2
result += result.T                               # 3
print(result)

产生

[[  0.    12.99   5.85  10.22   3.95]
 [ 12.99   0.     5.12   3.45   4.1 ]
 [  5.85   5.12   0.     5.05   8.1 ]
 [ 10.22   3.45   5.05   0.    15.45]
 [  3.95   4.1    8.1   15.45   0.  ]]
  1. 制作一个填充零的数组
  2. np.triu_indices(s.shape[0], 0)返回形状(s.shape[0], s.shape[0])数组的上三角形的索引。

    In [95]: np.triu_indices(5, 0)
    Out[95]: 
    (array([0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4]),
     array([0, 1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 4, 3, 4, 4]))
    

    result[...] = end使用end中的值填充上三角形。

  3. 进行result的转置并将其添加到result,从而使result对称。

  4. 这使您可以在不调用mahalanobis(s[i], s[j])mahalanobis(s[j], s[i])的情况下获取结果,这是不必要的,因为mahalanbis距离是对称的。


    请注意,对角线始终为零,因为mahalanobis(x,x)等于零 任何x。因此,为了提高效率,您可以排除对角线:

    end =[]
    for i in range(len(s)):
        for j in range(i+1, len(s)):              # <-- note i+1
            out = mahalanobis(s[i], s[j], invcov)       
            end.append(out)
    

    然后使用与之前相同的代码构建result,但现在我们可以使用

    result[np.triu_indices(s.shape[0], 1)] = end     
    

    而不是

    result[np.triu_indices(s.shape[0], 0)] = end     
    

    np.triu_indices的第二个参数控制对角线偏移。当偏移量为1时,省略与主对角线对应的索引。

    In [96]: np.triu_indices(5, 1)
    Out[96]: (array([0, 0, 0, 0, 1, 1, 1, 2, 2, 3]), array([1, 2, 3, 4, 2, 3, 4, 3, 4, 4]))
    

答案 2 :(得分:0)

你的循环很好,如​​果你只是添加一个计数器和第二个数组,那么你可以在一个数组中将结果分组为5个元素(如果这是所需的结果)

end =[]
tmp =[]
for i in range(len(s)):
    for j in range(i, len(s)):
        out = mahalanobis(s[i], s[j], invcov)
        if k % 5 == 0 and k != 0:
            end.append(tmp)
            tmp =[]       
        k += 1
        tmp.append(out)
if len(tmp) > 0:
    end.append(tmp)
print end

无论您的输入是什么,您的输出都将是一个包含n个数组的数组,每个数组包含5个成员[[1,2,3,4,5],[...],[...], ... ]

答案 3 :(得分:0)

另一种方法是使用你的代码,并在其下面:

end2 = []
for repeat in range(len(end)/5-1):
    end2.append(end[0:4])
    end = end[5:]

答案 4 :(得分:0)

这是一个直接的迭代,它将out的元素分配给对称矩阵:

x=np.zeros((5,5))
cnt=0
for i in range(5):
    for j in range(i,5):
        x[j,i] =x[i,j] = out[cnt]
        cnt += 1
制造

array([[  0.  ,  12.99,   5.85,  10.22,   3.95],
       [ 12.99,   0.  ,   5.12,   3.45,   4.1 ],
       [  5.85,   5.12,   0.  ,   5.05,   8.1 ],
       [ 10.22,   3.45,   5.05,   0.  ,  15.45],
       [  3.95,   4.1 ,   8.1 ,  15.45,   0.  ]])

由于此迭代与原始迭代平行,您可以立即构建矩阵:

n = s.shape[0]
x = np.zeros((n,n))
for i in range(n):
    for j in range(i+1, n):
        x[i,j] = x[j,i] = mahalanobis(s[i], s[j], invcov)       
print x

我在内部循环中使用i+1,因为显然mahalanobisi==j为0。