Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将大数据帧输出到CSV文件的最快方法是什么?_Python_Performance_Pandas_Output - Fatal编程技术网

Python 将大数据帧输出到CSV文件的最快方法是什么?

Python 将大数据帧输出到CSV文件的最快方法是什么?,python,performance,pandas,output,Python,Performance,Pandas,Output,对于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.

对于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
问题:

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

注意:我的测试是在Linux服务器上的本地驱动器上使用pandas 0.9.1完成的。

您的
df_to_csv
功能非常好,只是它做了很多假设,不适用于一般情况

如果它对你有效,那很好,但是要知道它不是一个通用的解决方案。CSV可以包含逗号,那么如果要写入这个元组会发生什么呢<代码>('a,b','c')

python
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')
#数据是一个包含元组的元组
对于数据中的行:
对于X范围内的列(列(行)):
f、 写入(“%d%”行[col])
如果列<列(行)-1:
f、 写入(',')
f、 写入('\n')

我不知道那样会不会更快。如果不是,那是因为完成了太多的系统调用,所以您可能会使用
StringIO
而不是直接输出,然后每隔一段时间将其转储到实际文件中

Lev。熊猫已经将
改写为_csv
,大大提高了本地速度。这个过程现在是i/o绑定的,考虑了许多微妙的数据类型问题和引用案例。以下是我们与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
因此,对于单个数据类型(例如float),不太宽的吞吐量约为20M rows/min,下面是上面的示例

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

使用chunksize。我发现这有很大的不同。如果您手头有内存,请使用好的chunksize(行数)进入内存,然后写一次

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
相比)

以Python3.7、pandas 0.23.4和numpy 1.15.2为基准(
xrange
range
替换,以使问题中发布的函数在Python3中起作用)


另外,如果需要包含索引,
savetxt
可以正常工作-只需传递
df.reset_index().values
并相应地调整格式字符串。

我最近刚刚使用内置的to_excel和to_csv DataFrame方法从数据框groupby批量导出大约1.7K个报告,以及部分报告(尤其是较大的文件)出来时已损坏。我现在相当怀疑这些内置过程,并计划为我的工作流自制我自己的导出函数。@DavidMarx您能发布一个损坏文件、数据帧和代码的示例吗?这将极大地帮助我们调试问题。谢谢。这是我为我的办公室构建的一个常用工具。我将看看我是否不能用非workplace-sensitive.FWIW的数据复制这个问题。对于这种类型的数据集,它通常需要支付存储在HDF5中的费用,特别是如果您需要查询,请参阅,我正在尝试输出一个100000*100000数据帧,这需要花费很长时间=(我组合了90多个csv文件,每个文件选择特定的4列,只有3个文件超过20000KB,其他文件在平均10000KB以下,一些文件是零行,然后到_csv,需要17分钟。结果csv是20000KB,这一次有意义吗?我如何优化?@Jeff是默认的chunksize 1还是什么?你使用什么chunksize?它是dn对我来说似乎没有什么区别,即使设置chunksize=500000发现它,它可能是1…@words如果列数>100000,chunksize只有1,否则它是100000//尝试将1600万行写入CSV的列数。使用chunksize=1000000,这将写入速度提高了10倍。使用c5.9xlarge EC2 instanceIm收到以下错误:ValueError:fmt的%formats数量错误:%d、%.1f、%.1f、%.1f、%.1f请确保格式字符串与列的数量相同。答案与问题中的测试用例完全一致,对于其他数据帧,它将需要调整。就其价值而言,pandas to_csv不再落后太多(我在V0.23.4上):
timeit(“aa.to_csv('temp.csv',index=False)”,globals=globals(),number=5)
37.9s
timeit(“np.savetxt('temp.csv',aa.values,fmt='%d,%.1f,%.1f',header=','。join(aa.columns),comments=''”,globals=globals(),number=5)
33.7s
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