Python: 如何从一行值创建一个完整的距离矩阵?
Python: How to create a complete distance matrix from a row of values?
您好,我想构建一个大小为 10 x 10 的距离矩阵,并且我生成了一个值列表,其中包含 45 个实数以填充 10 x 10 矩阵。距离矩阵也称为对称矩阵,它是矩阵另一侧的镜像。我目前的情况是我有 45 个值我想知道如何创建距离矩阵并在矩阵的对角线部分填充 0 并创建镜像矩阵以形成完整的距离矩阵。
例如,
1, 2, 4, 3, 5, 6
输出:
0, 1, 2, 4
1, 0, 3, 5
2, 3, 0, 6
4、5、6、0
谢谢。
所以,听起来您想使用 numpy 数组。
import numpy as np
yourarray = np.zeros([10,10])
这构成了一个十乘十的数组,其中填充了零。
然后,为了填充它,您想要走出一个三角形,并用下一个值填充每个连续的对象。因此,在每个对象只是下一个整数的基本情况下,
count = 1
for ii in range(1,10):
for jj in range(ii):
yourarray[ii,jj] = yourarray[jj,ii] = count
count +=1
如果您有一个包含 45 个数字的列表,您可以替换
yourarray[ii,jj] = yourarray[jj,ii] = count
和
yourarray[ii,jj] = yourarray[jj,ii] = vallist[count]
其中 vallist 是您的 45 个对象的列表。在这种情况下,将代码开头的 count = 1
替换为 count = 0
(因为 Python 是 0 索引)。
详情
为避免填充对角线,jj 设置为 range(ii)
。由于 python returns [0, 1, 2, ... N - 2, N -1]
中的 range(N),那么你永远不会有 jj=ii
。此外,由于 jj 只上升到 ii,但不会变得更大(如果 jj 也是 in range(1,10)
也会发生这种情况),这将只处理对角线正确一侧的数组的每一侧。
这样的怎么样?
# Create a zero matrix of w x h
w, h = 10, 10
matrix = [[0] * w for i in range(h)]
# List of your numbers
numbers = range(1,46)
# Fill your numbers in
# go one row at a time and fill until you reach the diagonal
for i in range(10):
for j in range(0, i):
matrix[i][j] = matrix[j][i] = numbers.pop(0)
# Print all rows
for row in matrix:
print row
你得到的输出是:
[0, 1, 2, 4, 7, 11, 16, 22, 29, 37]
[1, 0, 3, 5, 8, 12, 17, 23, 30, 38]
[2, 3, 0, 6, 9, 13, 18, 24, 31, 39]
[4, 5, 6, 0, 10, 14, 19, 25, 32, 40]
[7, 8, 9, 10, 0, 15, 20, 26, 33, 41]
[11, 12, 13, 14, 15, 0, 21, 27, 34, 42]
[16, 17, 18, 19, 20, 21, 0, 28, 35, 43]
[22, 23, 24, 25, 26, 27, 28, 0, 36, 44]
[29, 30, 31, 32, 33, 34, 35, 36, 0, 45]
[37, 38, 39, 40, 41, 42, 43, 44, 45, 0]
假设您要创建任意大小的距离矩阵:
import math
def distance_matrix(pattern):
# to get the side length, solve for n where len(pattern) = n*(n + 1)/2 (triangular number formula)
side_length = (int(math.sqrt(1 + 8 * len(pattern))) - 1) // 2 + 1
assert (side_length * (side_length - 1)) // 2 == len(pattern), "Pattern length must be a triangular number."
# create the grid
grid = [[0] * side_length for i in range(side_length)]
# fill in the grid
position = 0
for i in range(0, side_length - 1):
for j in range(0, side_length - 1 - i):
element = pattern[position]; position += 1
grid[i][i + j + 1] = element # fill in the upper triangle
grid[i + j + 1][i] = element # fill in the lower triangle
return grid
def matrix_to_string(matrix): return "\n".join("\t".join(str(x) for x in row) for row in distance_matrix([1, 2, 4, 3, 5, 6]))
if __name__ == "__main__":
print(matrix_to_string(distance_matrix([1, 2, 4, 3, 5, 6])))
编辑:边长需要是一个整数。否则你会得到这个错误:'float' object cannot be interpreted as an integer。解决方法是添加楼层除法运算符 \。
如果您使用的是 NumPy,这将是 numpy.triu_indices
的完美工作,其中 returns 一对适合选择矩阵上三角的索引数组。第一个参数是矩阵的边长,第二个参数是从哪条对角线开始:
In [1]: import numpy
In [2]: x = numpy.zeros([4, 4]) # 4x4 array of zeros
In [3]: x[numpy.triu_indices(4, 1)] = [1, 2, 4, 3, 5, 6]
In [4]: x
Out[4]:
array([[ 0., 1., 2., 4.],
[ 0., 0., 3., 5.],
[ 0., 0., 0., 6.],
[ 0., 0., 0., 0.]])
In [5]: x += x.T
In [6]: x
Out[6]:
array([[ 0., 1., 2., 4.],
[ 1., 0., 3., 5.],
[ 2., 3., 0., 6.],
[ 4., 5., 6., 0.]])
使用SciPy,使用scipy.spatial.distance.squareform
:
>>> scipy.spatial.distance.squareform([1,2,3,4,5,6])
array([[ 0., 1., 2., 3.],
[ 1., 0., 4., 5.],
[ 2., 4., 0., 6.],
[ 3., 5., 6., 0.]])
您好,我想构建一个大小为 10 x 10 的距离矩阵,并且我生成了一个值列表,其中包含 45 个实数以填充 10 x 10 矩阵。距离矩阵也称为对称矩阵,它是矩阵另一侧的镜像。我目前的情况是我有 45 个值我想知道如何创建距离矩阵并在矩阵的对角线部分填充 0 并创建镜像矩阵以形成完整的距离矩阵。
例如,
1, 2, 4, 3, 5, 6
输出:
0, 1, 2, 4
1, 0, 3, 5
2, 3, 0, 6
4、5、6、0
谢谢。
所以,听起来您想使用 numpy 数组。
import numpy as np
yourarray = np.zeros([10,10])
这构成了一个十乘十的数组,其中填充了零。
然后,为了填充它,您想要走出一个三角形,并用下一个值填充每个连续的对象。因此,在每个对象只是下一个整数的基本情况下,
count = 1
for ii in range(1,10):
for jj in range(ii):
yourarray[ii,jj] = yourarray[jj,ii] = count
count +=1
如果您有一个包含 45 个数字的列表,您可以替换
yourarray[ii,jj] = yourarray[jj,ii] = count
和
yourarray[ii,jj] = yourarray[jj,ii] = vallist[count]
其中 vallist 是您的 45 个对象的列表。在这种情况下,将代码开头的 count = 1
替换为 count = 0
(因为 Python 是 0 索引)。
详情
为避免填充对角线,jj 设置为 range(ii)
。由于 python returns [0, 1, 2, ... N - 2, N -1]
中的 range(N),那么你永远不会有 jj=ii
。此外,由于 jj 只上升到 ii,但不会变得更大(如果 jj 也是 in range(1,10)
也会发生这种情况),这将只处理对角线正确一侧的数组的每一侧。
这样的怎么样?
# Create a zero matrix of w x h
w, h = 10, 10
matrix = [[0] * w for i in range(h)]
# List of your numbers
numbers = range(1,46)
# Fill your numbers in
# go one row at a time and fill until you reach the diagonal
for i in range(10):
for j in range(0, i):
matrix[i][j] = matrix[j][i] = numbers.pop(0)
# Print all rows
for row in matrix:
print row
你得到的输出是:
[0, 1, 2, 4, 7, 11, 16, 22, 29, 37]
[1, 0, 3, 5, 8, 12, 17, 23, 30, 38]
[2, 3, 0, 6, 9, 13, 18, 24, 31, 39]
[4, 5, 6, 0, 10, 14, 19, 25, 32, 40]
[7, 8, 9, 10, 0, 15, 20, 26, 33, 41]
[11, 12, 13, 14, 15, 0, 21, 27, 34, 42]
[16, 17, 18, 19, 20, 21, 0, 28, 35, 43]
[22, 23, 24, 25, 26, 27, 28, 0, 36, 44]
[29, 30, 31, 32, 33, 34, 35, 36, 0, 45]
[37, 38, 39, 40, 41, 42, 43, 44, 45, 0]
假设您要创建任意大小的距离矩阵:
import math
def distance_matrix(pattern):
# to get the side length, solve for n where len(pattern) = n*(n + 1)/2 (triangular number formula)
side_length = (int(math.sqrt(1 + 8 * len(pattern))) - 1) // 2 + 1
assert (side_length * (side_length - 1)) // 2 == len(pattern), "Pattern length must be a triangular number."
# create the grid
grid = [[0] * side_length for i in range(side_length)]
# fill in the grid
position = 0
for i in range(0, side_length - 1):
for j in range(0, side_length - 1 - i):
element = pattern[position]; position += 1
grid[i][i + j + 1] = element # fill in the upper triangle
grid[i + j + 1][i] = element # fill in the lower triangle
return grid
def matrix_to_string(matrix): return "\n".join("\t".join(str(x) for x in row) for row in distance_matrix([1, 2, 4, 3, 5, 6]))
if __name__ == "__main__":
print(matrix_to_string(distance_matrix([1, 2, 4, 3, 5, 6])))
编辑:边长需要是一个整数。否则你会得到这个错误:'float' object cannot be interpreted as an integer。解决方法是添加楼层除法运算符 \。
如果您使用的是 NumPy,这将是 numpy.triu_indices
的完美工作,其中 returns 一对适合选择矩阵上三角的索引数组。第一个参数是矩阵的边长,第二个参数是从哪条对角线开始:
In [1]: import numpy
In [2]: x = numpy.zeros([4, 4]) # 4x4 array of zeros
In [3]: x[numpy.triu_indices(4, 1)] = [1, 2, 4, 3, 5, 6]
In [4]: x
Out[4]:
array([[ 0., 1., 2., 4.],
[ 0., 0., 3., 5.],
[ 0., 0., 0., 6.],
[ 0., 0., 0., 0.]])
In [5]: x += x.T
In [6]: x
Out[6]:
array([[ 0., 1., 2., 4.],
[ 1., 0., 3., 5.],
[ 2., 3., 0., 6.],
[ 4., 5., 6., 0.]])
使用SciPy,使用scipy.spatial.distance.squareform
:
>>> scipy.spatial.distance.squareform([1,2,3,4,5,6])
array([[ 0., 1., 2., 3.],
[ 1., 0., 4., 5.],
[ 2., 4., 0., 6.],
[ 3., 5., 6., 0.]])