2016-06-21 163 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