2016-07-29 12 views
3

バイナリファイルを読み取り、DataFrameを初期化するために使用できるデータを返すパッケージを作成しています。 dictまたは2つのリスト(キーを保持するものと値を保持するもの)。メモリ使用量、Dictを使用するDictを使用したPandas DataFrameのキーと値の使用リスト

私が作っているパッケージは、DataFrameオブジェクトに完全に依存しているとは考えられません。そのため、私のパッケージは現在、(容易なアクセスのために)dictというデータを出力しています。メモリとスピードの節約(何百万というデータポイントを処理しているので、私のアプリケーションには最優先)がある場合は、代わりにキーと値のリストを出力したいと考えています。これらのイテラブルは、DataFrameの初期化に使用されます。

In [1]: d = {(1,1,1): '111', 
    ...: (2,2,2): '222', 
    ...: (3,3,3): '333', 
    ...: (4,4,4): '444'} 

In [2]: keyslist=[(1,1,1),(2,2,2),(3,3,3),(4,4,4)] 

In [3]: valslist=['111','222','333','444'] 

In [4]: import pandas as pd 

In [5]: dfdict=pd.DataFrame(d.values(), index=pd.MultiIndex.from_tuples(d.keys(), names=['a','b','c'])) 

In [6]: dfdict 
Out[6]: 
     0 
a b c  
3 3 3 333 
2 2 2 222 
1 1 1 111 
4 4 4 444 

In [7]: dflist=pd.DataFrame(valslist, index=pd.MultiIndex.from_tuples(keyslist, names=['a','b','c'])) 

In [8]: dfpair 
Out[8]: 
     0 
a b c  
1 1 1 111 
2 2 2 222 
3 3 3 333 
4 4 4 444 

それはd.values()d.keys()は、データの新しいコピーを作成しているというのが私の理解は次のとおりです。ここで

は簡単な例です。もし dictlistよりも多くのメモリを必要とし、と d.keys()を使用してメモリ使用量が増えるという事実を無視すれば、 listペアの実装は可能ですか?

+0

代わりにnumpy配列を使用してみませんか?彼らはリストと辞書の両方よりもはるかに少ないメモリフットプリントを持っています –

+0

私はデータのサイズがわからないのでnumpyを使用していないので、リストや辞書を作成してからnumpy配列やpandas Dataframeを初期化しなければなりません。 – snowleopard

+0

リストのメモリ使用量のベンチマークを書くでしょう –

答えて

3

私は1M行のメモリプロファイリングを行いました。勝利した構造は、すべての数値インデックスに対してarray.arrayを使用し、文字列(147MBのデータと310MBのパンダへの変換)のリストを使用することです。

は、Pythonのマニュアルによると

配列は、シーケンス型であり、それらに格納されているオブジェクトの種類が制約されること を除き、非常に多くのリストのように振る舞います。

これらのメソッドにも追加メソッドがあり、非常に高速の追加速度を持つ可能性があります。

2位は2つの別々のリストになります。 (308MBと450MB)

dictを使用し、タプルが4つのリストを使用する他の2つのオプションは、最悪でした。 Dict:339MB、524MB。 4つのリスト:308MB、514MB。

ここでは配列の使用方法を示します。配列:4のタプルの

一覧::ここで

In [1]: from array import array 
In [2]: import gc 
In [3]: import pandas as pd 
In [4]: %load_ext memory_profiler 
In [5]: a1=array("l",range(1000000)) 
In [6]: a2=array("l",range(1000000)) 
In [7]: a3=array("l",range(1000000)) 
In [8]: b=[str(x*111) for x in list(range(1000000))] 
In [9]: gc.collect() 
Out[9]: 0 
In [10]: %memit a1,a2,a3,b 
peak memory: 147.64 MiB, increment: 0.32 MiB 
In [11]: %memit dfpair=pd.DataFrame(b, index=pd.MultiIndex.from_arrays([a1,a2,a3], names=['a','b','c'])) 
peak memory: 310.60 MiB, increment: 162.91 MiB 

は、(非常に長い)コードの残りの部分である

In [1]: import gc 
In [2]: import pandas as pd 
In [3]: %load_ext memory_profiler 
In [4]: a=list(zip(list(range(1000000)),list(range(1000000)),list(range(1000000)))) 
In [5]: b=[str(x*111) for x in list(range(1000000))] 
In [6]: d2=[x+(b[i],) for i,x in enumerate(a)] 
In [7]: del a 
In [8]: del b 
In [9]: gc.collect() 
Out[9]: 0 
In [10]: %memit d2 
peak memory: 308.40 MiB, increment: 0.28 MiB 
In [11]: %memit df = pd.DataFrame(d2, columns=['a','b','c','d']).set_index(['a','b','c']) 
peak memory: 514.21 MiB, increment: 205.80 MiB 

辞書:

In [1]: import gc 
In [2]: import pandas as pd 
In [3]: %load_ext memory_profiler 
In [4]: a=list(zip(list(range(1000000)),list(range(1000000)),list(range(1000000)))) 
In [5]: b=[str(x*111) for x in list(range(1000000))] 
In [6]: d = dict(zip(a, b)) 
In [7]: del a 
In [8]: del b 
In [9]: gc.collect() 
Out[9]: 0 
In [10]: %memit d 
peak memory: 339.14 MiB, increment: 0.23 MiB 
In [11]: %memit dfdict=pd.DataFrame(list(d.values()), index=pd.MultiIndex.from_tuples(d.keys(), names=['a','b','c'])) 
peak memory: 524.10 MiB, increment: 184.95 MiB 

2個のアレイ:

In [1]: import gc 
In [2]: import pandas as pd 
In [3]: %load_ext memory_profiler 
In [4]: a=list(zip(list(range(1000000)),list(range(1000000)),list(range(1000000)))) 
In [5]: b=[str(x*111) for x in list(range(1000000))] 
In [6]: gc.collect() 
Out[6]: 0 
In [7]: %memit a,b 
peak memory: 307.75 MiB, increment: 0.19 MiB 
In [8]: %memit dfpair=pd.DataFrame(b, index=pd.MultiIndex.from_tuples(a, names=['a','b','c'])) 
peak memory: 459.94 MiB, increment: 152.19 MiB 
ここで
+0

ありがとう!私はまた、辞書がリストと同様に実行されなかったことを知った。すべての素晴らしいポインタのおかげで、配列にもっと見ていきます。私は自分の発見を掲載する予定です。 – snowleopard

0

memory_profilerを使用してベンチマークです:同じタスクとメモリの種類については

Filename: testdict.py 

Line # Mem usage Increment Line Contents 
================================================ 
    4  66.2 MiB  0.0 MiB @profile 
    5        def testdict(): 
    6 
    7  66.2 MiB  0.0 MiB  d = {} 
    8 
    9 260.6 MiB 194.3 MiB  for i in xrange(0,1000000): 
    10 260.6 MiB  0.0 MiB    d[(i,i,i)]=str(i)*3 
    11 
    12 400.2 MiB 139.6 MiB  dfdict=pd.DataFrame(d.values(), index= 
pd.MultiIndex.from_tuples(d.keys(), names=['a','b','c'])) 

Filename: testlist.py 

Line # Mem usage Increment Line Contents 
================================================ 
    4  66.5 MiB  0.0 MiB @profile 
    5        def testlist(): 
    6 
    7  66.5 MiB  0.0 MiB  keyslist=[] 
    8  66.5 MiB  0.0 MiB  valslist=[] 
    9 
    10 229.3 MiB 162.8 MiB  for i in xrange(0,1000000): 
    11 229.3 MiB  0.0 MiB    keyslist.append((i,i,i)) 
    12 229.3 MiB  0.0 MiB    valslist.append(str(i)*3) 
    13 
    14 273.6 MiB  44.3 MiB  dflist=pd.DataFrame(valslist, index= 
pd.MultiIndex.from_tuples(keyslist, names=['a','b','c'])) 

、辞書の実装は、メモリとして効率的ではないようです。

編集

私は数字の配列に値を変更するいくつかの理由で、(私のデータのより代表)のために、私は、非常によく似たパフォーマンスを得るなぜこれが起こっている誰もが知っているのですか?

Filename: testdict.py 

Line # Mem usage Increment Line Contents 
================================================ 
    4  66.9 MiB  0.0 MiB @profile 
    5        def testdict(): 
    6 
    7  66.9 MiB  0.0 MiB  d = {} 
    8 
    9 345.6 MiB 278.7 MiB  for i in xrange(0,1000000): 
    10 345.6 MiB  0.0 MiB    d[(i,i,i)]=[0]*9 
    11 
    12 546.2 MiB 200.6 MiB  dfdict=pd.DataFrame(d.values(), index= 
pd.MultiIndex.from_tuples(d.keys(), names=['a','b','c'])) 

Filename: testlist.py 

Line # Mem usage Increment Line Contents 
================================================ 
    4  66.3 MiB  0.0 MiB @profile 
    5        def testlist(): 
    6 
    7  66.3 MiB  0.0 MiB  keyslist=[] 
    8  66.3 MiB  0.0 MiB  valslist=[] 
    9 
    10 314.7 MiB 248.4 MiB  for i in xrange(0,1000000): 
    11 314.7 MiB  0.0 MiB    keyslist.append((i,i,i)) 
    12 314.7 MiB  0.0 MiB    valslist.append([0]*9) 
    13 
    14 515.2 MiB 200.6 MiB  dflist=pd.DataFrame(valslist, index= 
pd.MultiIndex.from_tuples(keyslist, names=['a','b','c'])) 
+0

Pythonの文字列は、以前の文字列を記憶しています。したがって、 "000"は別の "000"と同じメモリを占有します。そして、 "1000"は実際には "000"文字列にリンクする1バイトである可能性があります。数字はそれをすることができませんでした。 –

関連する問題