根据文件中的数据在Python中构建对称矩阵

时间:2014-05-08 00:40:33

标签: python

我有一个文件,例如:

1  1  5.5
1  2  6.1
1  3  7.3
2  2  3.4
2  3  9.2
3  3  4.7

这是对称3x3矩阵的“一半”。我想在Python中创建完整的对称矩阵,看起来像

[[ 5.5 6.1 7.3] 
 [ 6.1 3.4 9.2]
 [ 7.3 9.2 4.7]]

(当然我的实际文件是NxN矩阵的“更大'的一半'所以我需要一个解决方案,而不是逐个输入值)

我已经耗尽了我所有的资源(书籍和互联网),到目前为止我所拥有的资源并没有真正接近。有人可以帮我这个吗?

谢谢!

3 个答案:

答案 0 :(得分:0)

读取文件并将其作为python对象加载,这是一个解决方案:

import numpy

m = numpy.matrix([[0,0,0],[0,0,0],[0,0,0]])

with file('matrix.txt', 'r') as f:
    for l in f:
        try:
            i, j, val = line.split(' ')
            i, j, val = int(i), int(j), float(val)
            m[i-1,j-1] = val
        except:
            print("couldn't load line: {}".format(l))

print m

答案 1 :(得分:0)

这是在Numpy中完全执行此操作的另一种方法。两个重要的评论:

  • 您可以使用np.loadtxt功能
  • 直接阅读
  • 您可以将上半部分值分配给一行中的正确索引:N[idxs[:,0] - 1, idxs[:,1] - 1] = vals

以下是代码:

import numpy as np    
from StringIO import StringIO

indata = """
1  1  5.5
1  2  6.1
1  3  7.3
2  2  3.4
2  3  9.2
3  3  4.7
"""

infile = StringIO(indata)

A = np.loadtxt(infile)

# A is
# array([[ 1. ,  1. ,  5.5],
#        [ 1. ,  2. ,  6.1],
#        [ 1. ,  3. ,  7.3],
#        [ 2. ,  2. ,  3.4],
#        [ 2. ,  3. ,  9.2],
#        [ 3. ,  3. ,  4.7]])

idxs = A[:, 0:2].astype(int)
vals = A[:, 2]

## To find out the total size of the triangular matrix, note that there
## are only n * (n + 1) / 2 elements that must be specified (the upper
## half amount for (n^2 - n) / 2, and the diagonal adds n to that).
## Therefore, the length of your data, A.shape[0], must be one solution
## to the quadratic equation: n^2 + 1 - 2 * A.shape[0] = 0
possible_sizes = np.roots([1, 1, -2 * A.shape[0]])

## Let us take only the positive solution to that equation as size of the
## result matrix
size = possible_sizes[possible_sizes > 0]

N = np.zeros([size] * 2)

N[idxs[:,0] - 1, idxs[:,1] - 1] = vals

# N is
# array([[ 5.5,  6.1,  7.3],
#        [ 0. ,  3.4,  9.2],
#        [ 0. ,  0. ,  4.7]])

## Here we could do a one-liner like
# N[idxs[:,1] - 1, idxs[:,0] - 1] = vals

## But how cool is it to add the transpose and subtract the diagonal? :)
M = N + np.transpose(N) - np.diag(np.diag(N))

# M is
# array([[ 5.5,  6.1,  7.3],
#        [ 6.1,  3.4,  9.2],
#        [ 7.3,  9.2,  4.7]])

答案 2 :(得分:0)

如果您事先知道矩阵的大小(听起来就像这样),那么以下内容就可以了(在Python 2和3中都有):

N = 3
symmetric = [[None]*N for _ in range(SIZE)]  # pre-allocate output matrix

with open('matrix_data.txt', 'r') as file:
    for i, j, val in (line.split() for line in file if line):
        i, j, val = int(i)-1, int(j)-1, float(val)
        symmetric[i][j] = val
        if symmetric[j][i] is None:
            symmetric[j][i] = val

print(symmetric)  # -> [[5.5, 6.1, 7.3], [6.1, 3.4, 9.2], [7.3, 9.2, 4.7]]

如果您未提前知道大小N,则可以预处理文件并确定给定的最大索引值。