什么是最快的方式输出的大数据帧到一个CSV文件?

问题描述 投票:20回答:4

对于Python /熊猫我发现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

注:在性能上的增加取决于dtypes。但它始终是真实的(至少在我的测试),其to_csv()的性能比非优化的Python慢​​得多。

如果我有4500万行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服务器上的本地驱动器上的大熊猫0.9.1完成。

python performance pandas output
4个回答
11
投票

列弗。熊猫改写to_csv,使本机的速度有了很大的改进。这个过程是现在I / O密集型,占了很多细微的D型问题,和报价情况。这里是我们的性能测试结果与0.10.1(在即将到来的0.11)的释放。这些都是在ms,更低的比率更好。

Results:
                                            t_head  t_baseline      ratio
name                                                                     
frame_to_csv2 (100k) rows                 190.5260   2244.4260     0.0849
write_csv_standard  (10k rows)             38.1940    234.2570     0.1630
frame_to_csv_mixed  (10k rows, mixed)     369.0670   1123.0412     0.3286
frame_to_csv (3k rows, wide)              112.2720    226.7549     0.4951

所以吞吐量为单个D型细胞(例如浮子),不能太宽为约20M的行/分钟,这里是从上方的例子。

In [12]: df = pd.DataFrame({'A' : np.array(np.arange(45000000),dtype='float64')}) 
In [13]: df['B'] = df['A'] + 1.0   
In [14]: df['C'] = df['A'] + 2.0
In [15]: df['D'] = df['A'] + 2.0
In [16]: %timeit -n 1 -r 1 df.to_csv('test.csv')
1 loops, best of 1: 119 s per loop

2
投票

使用CHUNKSIZE。我发现,坠地狱很大的差异。如果你手上的内存使用好CHUNKSIZE(没有行),以获得到内存中,然后写一次。


2
投票

在2019年这样的情况下,它可能会更好只使用numpy的。看时机:

aa.to_csv('pandas_to_csv', index=False)
# 6.47 s

df2csv(aa,'code_from_question', myformats=['%d','%.1f','%.1f','%.1f'])
# 4.59 s

from numpy import savetxt

savetxt(
    'numpy_savetxt', aa.values, fmt='%d,%.1f,%.1f,%.1f',
    header=','.join(aa.columns), comments=''
)
# 3.5 s

所以,你可以通过两个因素使用numpy的下调时间。这一点,当然,在附带的弹性减弱(相比于aa.to_csv时)为代价。

与Python 3.7,熊猫0.23.4基准,numpy的1.15.2(xrange改为range使从Python 3中的问题的工作张贴的功能)。

PS。如果您需要包括索引,savetxt将正常工作 - 只是通过df.rest_index().values并相应地调整格式化字符串。


1
投票

df_to_csv功能是非常好的,但它做了很多假设,对于一般情况下不工作。

如果你的作品,这是很好的,但是要注意,它不是一个通用的解决方案。 CSV可以包含逗号,所以会发生什么,如果有这样的元组写? ('a,b','c')

因此,没有出现混乱的蟒蛇csv模块将引述价值,如果报价中存在的任何值会逃脱引号。当然,产生的东西,在所有情况下的工作原理是慢得多。不过,我想你只有一串数字。

你可以试试这个,看看它是否是速度快:

#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直接输出,然后倾倒到一个真正的文件每一次。

© www.soinside.com 2019 - 2024. All rights reserved.