2016-11-21 9 views
1

私はタブ区切りのファイルを持っている:対応する値でSFrameヘッダにユニークな列を変換

$ echo -e 'abc\txyz\t0.9\nefg\txyz\t0.3\nlmn\topq\t0.23\nabc\tjkl\t0.5\n' > test.txt 
$ cat test.txt 
abc xyz 0.9 
efg xyz 0.3 
lmn opq 0.23 
abc jkl 0.5 

$ python 
>>> from sframe import SFrame 
>>> sf = SFrame.read_csv('test.txt', header=False, delimiter='\t', column_type_hints=[unicode, unicode, float]) 
[INFO] sframe.cython.cy_server: SFrame v2.1 started. Logging /tmp/sframe_server_1479718846.log 
>>> sf 
Columns: 
    X1 str 
    X2 str 
    X3 float 

Rows: 4 

Data: 
+-----+-----+------+ 
| X1 | X2 | X3 | 
+-----+-----+------+ 
| abc | xyz | 0.9 | 
| efg | xyz | 0.3 | 
| lmn | opq | 0.23 | 
| abc | jkl | 0.5 | 
+-----+-----+------+ 
[4 rows x 3 columns] 

目標は「X1」で構成された1つの一意の行があります異なるSFrameを達成することであるが私はSFrameせずにそれをやってみました

+-----+-----+-----+------+ 
| X1 | xyz | opq | jkl | 
+-----+-----+-----+------+ 
| abc | 0.9 | 0.0 | 0.5 | 
+-----+-----+-----+------+ 
| efg | 0.3 | 0.0 | 0.0 | 
+-----+-----+-----+------+ 
| lmn | 0.0 | 0.23| 0.0 | 
+-----+-----+-----+------+ 

:列はすなわち、 'X2' からの値です

>>> import io 
>>> with io.open('test.txt', 'r', encoding='utf8') as fin: 
...  for line in fin: 
...    if line.strip(): 
...      s,t,p = line.strip().split('\t') 
...      matrix[(s,t)] = float(p) 
... 
>>> matrix 
{(u'abc', u'jkl'): 0.5, (u'abc', u'xyz'): 0.9, (u'lmn', u'opq'): 0.23, (u'efg', u'xyz'): 0.3} 

>>> col1, col2 = zip(*matrix.keys()) 
>>> [[matrix.get((c1,c2), 0.0) for c2 in col2] for c1 in col1] 
[[0.5, 0.9, 0.0, 0.9], [0.5, 0.9, 0.0, 0.9], [0.0, 0.0, 0.23, 0.0], [0.0, 0.3, 0.0, 0.3]] 
>>> import numpy as np 
>>> np.array([[matrix.get((c1,c2), 0.0) for c2 in col2] for c1 in col1]) 
array([[ 0.5 , 0.9 , 0. , 0.9 ], 
     [ 0.5 , 0.9 , 0. , 0.9 ], 
     [ 0. , 0. , 0.23, 0. ], 
     [ 0. , 0.3 , 0. , 0.3 ]]) 
>>> SFrame(np.array([[matrix.get((c1,c2), 0.0) for c2 in col2] for c1 in col1])) 
Columns: 
    X1 array 

Rows: 4 

Data: 
+-----------------------+ 
|   X1   | 
+-----------------------+ 
| [0.5, 0.9, 0.0, 0.9] | 
| [0.5, 0.9, 0.0, 0.9] | 
| [0.0, 0.0, 0.23, 0.0] | 
| [0.0, 0.3, 0.0, 0.3] | 
+-----------------------+ 
[4 rows x 1 columns] 

しかし、それでも私は希望のSFrameを取得しません。 一意の列を対応する値を持つSFrameヘッダーに変換する方法を教えてください。I。達成:

+-----+-----+-----+------+ 
| X1 | xyz | opq | jkl | 
+-----+-----+-----+------+ 
| abc | 0.9 | 0.0 | 0.5 | 
+-----+-----+-----+------+ 
| efg | 0.3 | 0.0 | 0.0 | 
+-----+-----+-----+------+ 
| lmn | 0.0 | 0.23| 0.0 | 
+-----+-----+-----+------+ 

これを行うには簡単な方法が必要です。一意ではないと想像してください。列要素の最大100万になる可能性があり、SFrameのサイズが1,000,000 X 1,000,000になる可能性があります。したがって、SFrameまたはHDFはデータ構造のように必要であり、リストの数が少ない配列やネイティブのpythonリストではありません。

+0

これはパンダを使用して、本当に簡単ですDataFrame。あなたのデータのサイズを考えると、 'sd.to_dataframe()'を使って一時的にSFrameに変換することは可能でしょうか? –

答えて

1

あなたがしたいことは、df.pivot(index='X1', columns='X2', values='X3')またはdf.set_index(['X1','X2']).unstack('X2')(この記事の最後を参照)のいずれかを使用して、パンダでは本当に些細なことです。

SFrameにはどちらも存在しないようです。 (私は間違っている可能性があります、今までSFrameを使用したことはありませんが、私はドキュメンテーションで何の証拠も見つけられませんでした)。

希望の結果を得るには、SFrame.unstack()SFrame.unpack()を使用する必要があります。

from sframe import SFrame 
sf = SFrame.read_csv('test.txt', header=False, delimiter='\t', column_type_hints=[unicode, unicode, float]) 

拳、アンスタック:

sf2 = sf.unstack(['X2', 'X3'], new_column_name='dict_counts') 
sf2 

X1  dict_counts 
efg  {'xyz': 0.3} 
lmn  {'opq': 0.23} 
abc  {'jkl': 0.5, 'xyz': 0.9} 

次に展開します。

for c in out.column_names(): 
    out = out.fillna(c, 0) 
out 


X1  jkl  opq  xyz 
efg  0.0  0.0  0.3 
lmn  0.0  0.23 0.0 
abc  0.5  0.0  0.9 
を:あなたが欲しい場合

out = sf2.unpack('dict_counts', column_name_prefix='') 
out 

X1  jkl  opq  xyz 
efg  None None 0.3 
lmn  None 0.23 None 
abc  0.5  None 0.9 

最後に、あなたが0Noneを置き換えるためにfillnaすることができます


それを行うためのもう一つの粗製の方法はそれにそれを旋回させるために、パンダのデータフレームに変換することかもしれませんが、あなたのデータセットが大きすぎる場合、これは動作しない可能性があります:

import pandas as pd 
from sframe import SFrame 
sf = SFrame.read_csv('test.txt', header=False, delimiter='\t', column_type_hints=[unicode, unicode, float]) 
sf = SFrame(data=sf.to_dataframe().pivot(index='X1', columns='X2', values='X3').fillna(0).reset_index()) 
+0

偉大な答え!詳細な説明をありがとう! – alvas

+0

注:巨大なデータセットを展開するには、実際には時間がかかります。それで、0.0の疎データセットを埋めています; P – alvas

+0

好奇心の渦中に、あなたのデータのサイズとどのくらいの時間がかかりますか? –

関連する問題