32

python / pandasの場合、df.to_csv(fname)が毎分約1百万行の速度で動作することがわかりました。次のように、パフォーマンスを7倍向上させることができます。

def df2csv(df,fname,myformats=[],sep=','):
  """
    # function is faster than to_csv
    # 7 times faster for numbers if formats are specified, 
    # 2 times faster for strings.
    # Note - be careful. It doesn't add quotes and doesn't check
    # for quotes or separators inside elements
    # We've seen output time going down from 45 min to 6 min 
    # on a simple numeric 4-col dataframe with 45 million rows.
  """
  if len(df.columns) <= 0:
    return
  Nd = len(df.columns)
  Nd_1 = Nd - 1
  formats = myformats[:] # take a copy to modify it
  Nf = len(formats)
  # make sure we have formats for all columns
  if Nf < Nd:
    for ii in range(Nf,Nd):
      coltype = df[df.columns[ii]].dtype
      ff = '%s'
      if coltype == np.int64:
        ff = '%d'
      elif coltype == np.float64:
        ff = '%f'
      formats.append(ff)
  fh=open(fname,'w')
  fh.write(','.join(df.columns) + '\n')
  for row in df.itertuples(index=False):
    ss = ''
    for ii in xrange(Nd):
      ss += formats[ii] % row[ii]
      if ii < Nd_1:
        ss += sep
    fh.write(ss+'\n')
  fh.close()

aa=DataFrame({'A':range(1000000)})
aa['B'] = aa.A + 1.0
aa['C'] = aa.A + 2.0
aa['D'] = aa.A + 3.0

timeit -r1 -n1 aa.to_csv('junk1')    # 52.9 sec
timeit -r1 -n1 df2csv(aa,'junk3',myformats=['%d','%.1f','%.1f','%.1f']) #  7.5 sec

注:パフォーマンスの向上はdtypeによって異なります。しかし、(少なくとも私のテストでは)to_csv()のパフォーマンスが最適化されていないPythonよりもはるかに遅いことは常に真実です。

4,500万行のcsvファイルがある場合、次のようになります。

aa = read_csv(infile)  #  1.5 min
aa.to_csv(outfile)     # 45 min
df2csv(aa,...)         # ~6 min

質問:

What are the ways to make the output even faster?
What's wrong with to_csv() ? Why is it soooo slow ?

注:私のテストは、Linuxサーバーのローカルドライブでpandas0.9.1を使用して行われました。

4

4 に答える 4

4

チャンクサイズを使用します。私はそれが非常に多くの違いを生むことを発見しました。手元にメモリがある場合は、適切なチャンクサイズ (行数) を使用してメモリにアクセスし、一度書き込みます。

于 2016-01-13T11:59:25.910 に答える
1

df_to_csv多くの仮定を行い、一般的なケースでは機能しないことを除けば、あなたの関数は非常に優れています。

それがうまくいくのであれば、それは良いことですが、それは一般的な解決策ではないことに注意してください。CSV にはコンマを含めることができるので、このタプルを書き込む場合はどうなるでしょうか。('a,b','c')

Pythoncsvモジュールは、混乱が生じないようにその値を引用し、いずれかの値に引用符が存在する場合は引用符をエスケープします。もちろん、すべてのケースで機能するものを生成すると、はるかに遅くなります。しかし、あなたはたくさんの数しか持っていないと思います。

これを試して、より高速かどうかを確認できます。

#data is a tuple containing tuples

for row in data:
    for col in xrange(len(row)):
        f.write('%d' % row[col])
        if col < len(row)-1:
            f.write(',')
    f.write('\n')

そのほうが速いかどうかはわかりません。そうでない場合は、システム コールが多すぎるためです。そのためStringIO、直接出力の代わりに使用して、時々実際のファイルにダンプすることができます。

于 2013-03-15T10:25:08.880 に答える