2016-06-21 7 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'は常にペアになりますか?もしそうなら、それを2つの列に分けることができますか?それは処理する方が簡単かもしれません。 – Divakar

答えて

0

scikit_learnは、おそらく簡単に行うためのツールを持っているが、私は、基本的なPythonの/ numpyのソリューションを説明します。

生データ - 私はリストの内包とverious列を引き出すことができますリスト

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

のリスト。これは、非常に大規模なケースでは最速ではないかもしれませんが、今のところ問題を1つずつ簡単に解決する方法です。

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からこれらを引き出すことができますが、明らかに大きなリストを使用しています。それらはintの代わりに文字列にすることができます。

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の入力を直接作成するバージョンの私の編集履歴を参照してください)

+0

になります。 ([id in i]の[np.in1d(idset、i)]、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 
関連する問題