来自这个数组
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]]
答案 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. ]]
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
中的值填充上三角形。
进行result
的转置并将其添加到result
,从而使result
对称。
这使您可以在不调用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
,因为显然mahalanobis
为i==j
为0。