Dask.dataframe.to_parquet制作非常大的文件

时间:2019-04-24 14:30:50

标签: dask parquet

我正在将10个固定宽度的大文件(平均19GB)转换为实木复合地板。 我是通过堆叠固定宽度的文件来实现的

file_list = [files]

stacked_files = open(stacked.txt,'a')
for i in file_list:
    f = open(i)
    for line in f:
        stacked_files.write(line)
    f.close()
    print(i,(time.time() - file_start)//60)
stacked_files.close()

此过程需要3个小时才能完成。 然后,我使用dask读取文件,并将其转换为实木复合地板。 我已经安装了fastparquet

df = dd.read_fwf(stacked.txt, colspecs = colspecs, names = names)
df.to_parquet('parquet.parquet')

我计划对此进行一些处理,例如通过重置索引并在列上进行计算来对它进行排序,但是就我现在而言,我现在想了解一下如何将其更改为实木复合地板。 该文件已经运行了2天,已经制作了2200 151 MB文件,总计340gb,并且还在不断增长。 有没有一种方法可以将文件读入dask数据帧而无需将其堆叠,这会更快吗? 还有什么我可以更改的以减小输出文件的大小吗?我的理解是实木复合地板是经过压缩的,并且应小于.txt文件。

修改 添加了代码来重现该问题: 该代码在我的计算机上运行了4分钟。它创建了一个文件“ test.csv” 96兆字节 并创建了一个文件“ test.parquet” 239 MB。 我正在使用固定宽度的文件作为当前遇到问题的代码,但是csv似乎可以重现文件大小的三倍。

import dask.dataframe as dd
import pandas as pd
import random
import os
test_file_folder = 'folder'

#create 500 columns
colnames = []
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
first_letter = 0
for i in range(500):
    second_letter = i%26
    colnames.append(letters[first_letter]+letters[second_letter])
    if i%26 == 0 and i !=0:
        first_letter +=1

#create a dictionary with 100,000 data points in each key with column names as keys
df = {}
for i in colnames:
    temp = []
    for x in range(100000):
        temp.append(random.choice(letters))
    df[i] = temp

#create the df and send it to csv
df = pd.DataFrame.from_dict(df)

df.to_csv(os.path.join(test_file_folder,'test.csv'))

ddf = dd.read_csv(os.path.join(test_file_folder,'test.csv'))
ddf.to_parquet(os.path.join(test_file_folder,'test.parquet'))

1 个答案:

答案 0 :(得分:2)

您提供的代码产生100MB的CSV和93MB的镶木地板数据集。不同之处在于,可能您缺少快速的压缩库。

这对于随机文本数据而言并非不常见,通常压缩效果不佳。您可以使用固定宽度的列(fastparquet允许这样做,但很少使用)和分类/字典编码(这取决于数据的基数)可以使用一些技巧。

一些笔记

  • 500列很高,这意味着您实际上没有实木复合地板专用的“表格”数据;所有这些列的架构和详细信息块都占用空间,并且在文件之间重复
  • 由于列数高,每个分区的行数比通常的要少得多,因此,metadata的空间开销成比例地增加了
  • 可以放弃每个列块产生最小/最大统计信息,而不制作元数据文件,而是依靠每个文件中的模式相同;但这不是用户容易暴露的东西。 (前者仅存在于PR中)
  • 对于每个字符串,
  • 文本由(length)(data)个块存储,其中长度为4个字节;因此,如果每个文本字符串为2个字节,则它们将在镶木地板数据中存储为6个字节,在CSV中存储为3个字节(由于逗号)。变体编码将长度分开,以便可以有效地将它们存储为整数(由于它们都具有相同的值,因此非常有效),但是实木复合地板框架的 none 实际上实现了这一点。