【问题标题】:Create Sparse Matrix in Python在 Python 中创建稀疏矩阵
【发布时间】:2016-10-23 13:26:21
【问题描述】:

处理数据并希望创建一个稀疏矩阵以供以后用于聚类目的。

fileHandle = open('data', 'r')

for line in fileHandle:
    json_list = []
    fields = line.split('\t')
    json_list.append(fields[0])
    json_list.append(fields[1])
    json_list.append(fields[3])

现在的数据是这样的:

term, ids, quantity
['buick', '123,234', '500']
['chevy', '345,456', '300']
['suv','123', '100']

我需要的输出是这样的:

term, quantity, '123', '234', '345', '456', '567'
buick, 500, 1, 1, 0, 0, 0
chevy, 300, 0, 0, 1, 1, 0
suv,   100, 1, 0, 0, 0, 0

我尝试过使用 numpy 稀疏矩阵库,但没有成功。

【问题讨论】:

  • 你有什么格式的输入?你能列出可以重现这些示例数据的代码吗?
  • @Divakar 已添加,感谢提问
  • ids 总是成对出现吗?如果是这样,你能把它分成两列吗?这可能更容易处理。
  • this 可能有帮助
  • @Divakar 列长度可以是任意数字

标签: python numpy scikit-learn sparse-matrix sklearn-pandas


【解决方案1】:

scikit_learn 可能有工具可以轻松做到这一点,但我将演示一个基本的 Python/numpy 解决方案。

原始数据 - 列表列表

In [1150]: data=[['buick', '123,234', '500'],
                 ['chevy', '345,456', '300'],
                 ['suv','123', '100']]

我可以用列表推导提取出各种列。在一个非常大的案例中,这可能不是最快的,但目前它是一种逐个解决问题的简单方法。

In [1151]: terms=[row[0] for row in data]

In [1152]: terms
Out[1152]: ['buick', 'chevy', 'suv']

In [1153]: quantities=[int(row[2]) for row in data]

In [1154]: quantities
Out[1154]: [500, 300, 100]

创建可能的 id 列表。我可以从data 中提取这些,但显然您使用的是更大的列表。它们可以是字符串而不是整数。

In [1155]: idset=[123,234,345,456,567]

In [1156]: ids=[[int(i) for i in row[1].split(',')] for row in data]

In [1157]: ids
Out[1157]: [[123, 234], [345, 456], [123]]

np.in1d 是一个方便的工具,用于查找这些子列表在主列表中的位置。生成的idM 是特征矩阵,有很多 0 和一些 1。

In [1158]: idM=np.array([np.in1d(idset,i) for i in ids],int)

In [1159]: idM
Out[1159]: 
array([[1, 1, 0, 0, 0],
       [0, 0, 1, 1, 0],
       [1, 0, 0, 0, 0]])

我们可以用各种方式组装这些部件。

例如,可以使用以下方式创建结构化数组:

In [1161]: M=np.zeros(len(data),dtype='U10,int,(5)int')

In [1162]: M['f0']=terms

In [1163]: M['f1']=quantities

In [1164]: M['f2']=idM

In [1165]: M
Out[1165]: 
array([('buick', 500, [1, 1, 0, 0, 0]), ('chevy', 300, [0, 0, 1, 1, 0]),
       ('suv', 100, [1, 0, 0, 0, 0])], 
      dtype=[('f0', '<U10'), ('f1', '<i4'), ('f2', '<i4', (5,))])

idM 可以变成一个稀疏矩阵:

In [1167]: from scipy import sparse

In [1168]: c=sparse.coo_matrix(idM)

In [1169]: c
Out[1169]: 
<3x5 sparse matrix of type '<class 'numpy.int32'>'
    with 5 stored elements in COOrdinate format>

In [1170]: c.A
Out[1170]: 
array([[1, 1, 0, 0, 0],
       [0, 0, 1, 1, 0],
       [1, 0, 0, 0, 0]])

在这个探索中,首先创建更密集的数组,然后再创建一个稀疏的数组更容易。

但是sparse 提供了一个bmat 函数,可以让我从单行矩阵的列表中创建多行矩阵。 (有关直接构造 coo 输入的版本,请参阅我的编辑历史记录)

In [1220]: ll=[[sparse.coo_matrix(np.in1d(idset,i),dtype=int)] for i in ids]

In [1221]: sparse.bmat(ll)
Out[1221]: 
<3x5 sparse matrix of type '<class 'numpy.int32'>'
    with 5 stored elements in COOrdinate format>

In [1222]: sparse.bmat(ll).A
Out[1222]: 
array([[1, 1, 0, 0, 0],
       [0, 0, 1, 1, 0],
       [1, 0, 0, 0, 0]], dtype=int32)

【讨论】:

  • 在 1158 上不清楚您在 idM=np.array([np.in1d(idset,i) for i in ids],int) 中获得“idset”的位置
  • 与 [1155] 中的 idlist 相同。我定义了两个名称,但最终使用了idset。我从你想要的输出表中得到了值。
【解决方案2】:

我有一个懒惰的方法

data = [['term', 'ids', 'quantity'],
... ['buick', ['123', '234'], 500],
... ['chevy', ['345', '456'], 300],
... ['suv', ['123', '567'], 100]]
res = []
for i,line in enumerate(data):
...     if i == 0:
...         header = line
...     else:
...         temp  = {}
...         for j,ele in enumerate(line):
...             if j in [0,2]:
...                 temp.update( {header[j] : ele} )
...             else:
...                 for num in line[1]:
...                     temp.update( { num:1 } )
...         res.append(temp)

with open(filepath,'wb') as f:
...      w = csv.DictWriter(f,set( [ k for ele in res for k in ele.keys()] ))
...      w.writeheader()
...      w.writerows(res)

输出

term    456 567 345 123 234 quantity
buick               1   1   500
chevy   1       1           300
suv     1       1           100

【讨论】:

    猜你喜欢
    • 2017-01-28
    • 2012-01-10
    • 2017-03-31
    • 2018-12-14
    • 1970-01-01
    • 2016-07-29
    • 2019-07-22
    • 1970-01-01
    • 2011-03-23
    相关资源
    最近更新 更多