有效地将numpy数组转换为矩阵

时间:2016-07-05 16:40:29

标签: python numpy scikit-learn

我的数据格式如下:

['FACTOR_1','FACTOR_2",'VALUE"]
['A'       ,'A'       ,2.0    ]
['A'       ,'B'       ,3.0    ]
['A'       ,'C'       ,2.2    ]
['A'       ,'D'       ,2.6    ]
['B'       ,'A'       ,2.6    ]
['B'       ,'B'       ,1.0    ]
['B'       ,'C'       ,6.0    ]
['B'       ,'D'       ,7.7    ]
['C'       ,'A'       ,2.1    ]
....
['D'       ,'D'       ,2.6    ]

它位于数据框中,但我还是转换为numpy数组。

我希望将其转换为两个因素的矩阵。

我自己编码了,但我目前的做法是非常缓慢且低效,我有一个嵌套循环并且正在搜索因子的索引:

    no_of_factors = np.size(np.unique(cov_data['FACTOR_1']))
    factors = np.unique(cov_data['FACTOR_1'])

    cov_matrix = np.zeros((no_of_factors, no_of_factors))

    i = 0
    for factor_1 in factors:
        factor_indices = np.where(cov_data['FACTOR_1'] == factor_1)[0].tolist()
        j = 0
        for factor_2 in factors:
            factor_2_index = np.where(cov_data['FACTOR_2'][factor_indices] == factor_2)[0].tolist()
            if np.size(factor_2_index) > 1:
                self.log.error("Found duplicate factor")
            elif np.size(factor_2_index) == 0:
                var = 0
            else:
                factor_2_index = factor_2_index[0]
                var = cov_data['VALUE'][factor_2_index]
            cov_matrix[i][j] = var
            j += 1
        i += 1 

令人讨厌的是,数据也不完美,并且每个因素都没有值,例如因子C可能只有A和B的值而D可能会丢失,因此检查并设置为0

1 个答案:

答案 0 :(得分:1)

您的代码中存在错误,我使用sub_data数组行进行了更正。我还以一些显而易见的方式简化了代码:

def foo(cov_data):
    factors = np.unique(cov_data['FACTOR_1'])
    no_of_factors = factors.shape[0]
    cov_matrix = np.zeros((no_of_factors, no_of_factors))
    for i,factor_1 in enumerate(factors):
        factor_indices = np.where(cov_data['FACTOR_1'] == factor_1)[0]
        sub_data = cov_data[factor_indices]
        for j,factor_2 in enumerate(factors):
            factor_2_index = np.where(sub_data['FACTOR_2'] == factor_2)[0]
            if factor_2_index.shape[0]==1:
                cov_matrix[i, j] = sub_data['VALUE'][factor_2_index[0]]
            elif factor_2_index.shape[0] ==0:
                pass
            else:
                self.log.error("Found duplicate factor")
    return cov_matrix

如果我从列表中制作结构化数组

cov_data = np.array([tuple(i) for i in factors], dtype=[('FACTOR_1','|U1'),('FACTOR_2','|U1'),('VALUE','f')])      

我得到了cov_matrix

[[ 2.          3.          2.20000005  2.5999999 ]
 [ 2.5999999   1.          6.          7.69999981]
 [ 2.0999999   0.          0.          0.        ]
 [ 0.          0.          0.          2.5999999 ]]

我还没有使用过这种特征矩阵,但我认为它是学习scikit-learn等代码的最重要的任务。

有时sklearn人制作稀疏矩阵。这是一种简单的方法:

features1, ind1 = np.unique(cov_data['FACTOR_1'], return_inverse=True)
features2, ind2 = np.unique(cov_data['FACTOR_2'], return_inverse=True)
values = cov_data['VALUE']
from scipy import sparse
M = sparse.coo_matrix((values,(ind1, ind2)))

return_inverse给出了原始数组中每个唯一值的索引。因此实际上它将字符串转换为行或列索引。

此矩阵M.A的密集版本是相同的。

print(M)显示索引值三元组:

  (0, 0)    2.0
  (0, 1)    3.0
  (0, 2)    2.2
  (0, 3)    2.6
  (1, 0)    2.6
  (1, 1)    1.0
  (1, 2)    6.0
  (1, 3)    7.7
  (2, 0)    2.1
  (3, 3)    2.6

这个计算存在一些粗略的边缘,例如如何处理重复项(添加值),features的顺序以及如果一个列表不像另一个列表那样完成该怎么办。 unique对它们进行排序。

从索引构造密集矩阵也很容易:

cov_matrix = np.zeros((len(features1), len(features2)))
cov_matrix[ind1, ind2] = values
print(cov_matrix)

(同样,它可能无法正确处理重复)。