2016-06-21 160 views
0

使用数据并希望创建稀疏矩阵以便稍后用于群集目的。在Python中创建稀疏矩阵

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的稀疏矩阵库工作,但没有成功。

+0

您以什么格式输入?你能列出能够重现这些样本数据的代码吗? – Divakar

+0

@Divakar添加了它,谢谢您的询问 – jKraut

+0

'ids'会不会成对?如果是这样,你能把它分成两列吗?这可能更容易处理。 – Divakar

回答

0

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

的原始数据 - 列出

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

的名单,我可以拉出来verious列与列表内涵。这可能不是一个非常大的案例中最快的,但现在它是一个简单的方法来逐件解决问题。

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和几个。

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) 
+0

1158不清楚你在idM = np.array中获得了“idset” ([np.in1d(idset,i)for i in ids],int) – jKraut

+0

与[1155]中的idlist相同。我定义了两个名字,但最终使用了'idset'。我从你想要的输出表中得到了这些值。 – hpaulj

0

我有一个懒惰的方法

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