2017-09-19 22 views
1

私は約90データフレームを持っています。それぞれ約1Gbで約500万行あります。データフレーム間の行を一致させ、一致するすべての平均を取る

各90には、他のすべてのデータフレームと一致する一意のIDがあります。

これらの2の例では、私がどこID一致するすべてのフレームにわたって平均を取りたい

DF1

Year ID Value 
1950 1 0.4 
1950 2 0.2 
1950 3 0.1 
1950 4 0.8 

DF2

Year ID Value 
1951 1 0.9 
1951 2 0.6 
1951 3 0.7 
1951 4 0.6 

です。それぞれの個別のファイルは非常に大きいので、それらをすべてメモリに保持することはできません。私はアプローチを思いついたが、それは信じられないほど遅く、より良い方法を望んでいる。

現在のアプローチは、次のとおりです。

import pandas as pd 
import os 
import numpy as np 

#list with unique ids found in all frames 
uniques = np.arange(1,5000000, 1) 

#loop through files 
files = "C:/path_to_csvs" 

#empty dataframe to store all means 
final = pd.DataFrame() 

for i in uniques: 

    #empty dataframe to append a single matching unique ID 
    single_combined = pd.DataFrame() 

    for f in os.listdir(files): 

     df2 = pd.read_csv(os.path.join(files, f))  

     #select rows where the id's match 
     df2 = df2[(df2['ID'] == i)] 

     #if there is a match, append the row 
     if df2.shape[0] != 0: 

      single_combined = single_combined.append(df2) 

    #groupby ID to get the means of value 
    means = single_combined.groupby(['ID'])[['Value]].mean().reset_index() 

    #append the mean to the final dataframe 
    final = final.append(means) 

print(final) 
+0

2-3列で作業しているときに 'read_csv'のすべての列を読み込むのはなぜですか? – Zero

+0

実際のデータは50列で、必要のないデータは「Year」だけです。私はそれを落とすことができると思ったが、それが効率の向上をもたらすかどうかは分からない。 –

答えて

1

アイデアmean = sum/count、ので、それらのそれぞれのsumcountsize)を計算する、のすべてのファイルを一=ずつを読んでみましょう、とそれを合計し、累積値sumcountを保存します。すべてのファイルが完成したら、mean = sum/countと簡単に計算できます。

したがって、次のアプローチを検討してください。

import glob 

files = glob.glob('d:/temp/.data/46307213/*.csv') 

res = pd.DataFrame() 

for f in files: 
    res = pd.concat([res, 
        pd.read_csv(f).groupby('ID')['Value'] 
         .agg(['sum', 'size'])]) \ 
      .groupby('ID').sum() 

res['mean'] = res.pop('sum')/res.pop('size') 

デモ:

ソースCSVファイル:

1.csv:

Year,ID,Value 
1950,1,0.4 
1950,2,0.2 
1950,3,0.1 
1950,4,0.8 

2.csv:

Year,ID,Value 
1951,1,0.9 
1951,2,0.6 
1951,5,0.7 
1951,6,0.6 

3.csv:

Year,ID,Value 
1952,1,0.9 
1952,1,0.6 
1952,5,0.7 
1952,5,0.6 

結果:

In [103]: %paste 
import glob 

files = glob.glob('d:/temp/.data/46307213/*.csv') 
res = pd.DataFrame() 
for f in files: 
    res = pd.concat([res, 
        pd.read_csv(f).groupby('ID')['Value'] 
         .agg(['sum', 'size'])]) \ 
      .groupby('ID').sum() 
res['mean'] = res.pop('sum')/res.pop('size') 
print(res) 

## -- End pasted text -- 
     mean 
ID 
1 0.700000 
2 0.400000 
3 0.100000 
4 0.800000 
5 0.666667 
6 0.600000 

結論:各ファイルは一度だけディスクから起動読み込まれます。

+0

実際にデータをテストするのに少し時間がかかりますが、これがうまくいかない理由はありません。 –

+0

このアルゴリズムは 'O(#_of_unique_vals * #_of_files) 'と比較して複雑な' O(#_of_files) 'を持っています – MaxU

+0

うん、意味がある、ありがとう。 –

関連する問題