Dask.dataframe.to_parquet 制作非常大的文件
Dask.dataframe.to_parquet making extremely large file
我正在将 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')
我计划为此添加一些处理,例如通过重置索引和对列进行计算来对其进行排序,但现在在我学习 dask 时,我想看看将其更改为 parquet 是如何工作的。
这已经 运行ning 了 2 天了,已经制作了超过 2200 个 151 MB 的文件,总计 340GB,而且还在不断增加。
有没有一种方法可以在不堆叠文件的情况下将文件读入 dask 数据帧,这样会更快吗?
有什么我可以更改以使输出文件更小吗?我的理解是镶木地板是压缩的,应该小于 .txt 文件。
编辑
添加代码以重现问题:
这段代码在我的机器上用了 4 分钟 运行。它创建了一个文件 'test.csv'
96MB
并创建了一个文件 'test.parquet'
239MB。
我正在为我目前遇到问题的代码使用固定宽度文件,但 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'))
您提供的代码生成 100MB 的 CSV 和 93MB 的镶木地板数据集。不同之处在于,您可能缺少压缩库 snappy。
这对于随机文本数据来说并不少见,它通常无法很好地压缩。您可以使用固定宽度的列(fastparquet 允许这样做,但很少使用)和 categorical/dictionary 编码(这取决于数据的基数)来玩一些技巧。
一些笔记
- 500 列很高,这意味着您实际上没有 "tabular" 镶木地板的数据;所有这些列的架构和详细信息块占用 space 并在文件之间复制
- 由于列数较多,每个分区的行数比通常情况下少得多,因此 space 元数据的开销按比例增加
- 可以放弃为每个列块生成 min/max 统计信息并且不生成元数据文件,而是依赖于每个文件中相同的架构;但这不是很容易暴露给用户的东西。 (前者只存在于一个PR中)
- 文本为每个字符串按(长度)(数据)块存储,其中长度为4个字节;因此,如果每个文本字符串均为 2 个字节,则它们将在 parquet 数据中存储为 6 个字节,在 CSV 中存储为 3 个字节(因为有逗号)。一种变体编码将长度分开,以便它们可以有效地存储为整数(因为它们都是相同的值,所以工作得非常好)但是 parquet 框架的 none 实际上实现了这个。
我正在将 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')
我计划为此添加一些处理,例如通过重置索引和对列进行计算来对其进行排序,但现在在我学习 dask 时,我想看看将其更改为 parquet 是如何工作的。 这已经 运行ning 了 2 天了,已经制作了超过 2200 个 151 MB 的文件,总计 340GB,而且还在不断增加。 有没有一种方法可以在不堆叠文件的情况下将文件读入 dask 数据帧,这样会更快吗? 有什么我可以更改以使输出文件更小吗?我的理解是镶木地板是压缩的,应该小于 .txt 文件。
编辑 添加代码以重现问题: 这段代码在我的机器上用了 4 分钟 运行。它创建了一个文件 'test.csv' 96MB 并创建了一个文件 'test.parquet' 239MB。 我正在为我目前遇到问题的代码使用固定宽度文件,但 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'))
您提供的代码生成 100MB 的 CSV 和 93MB 的镶木地板数据集。不同之处在于,您可能缺少压缩库 snappy。
这对于随机文本数据来说并不少见,它通常无法很好地压缩。您可以使用固定宽度的列(fastparquet 允许这样做,但很少使用)和 categorical/dictionary 编码(这取决于数据的基数)来玩一些技巧。
一些笔记
- 500 列很高,这意味着您实际上没有 "tabular" 镶木地板的数据;所有这些列的架构和详细信息块占用 space 并在文件之间复制
- 由于列数较多,每个分区的行数比通常情况下少得多,因此 space 元数据的开销按比例增加
- 可以放弃为每个列块生成 min/max 统计信息并且不生成元数据文件,而是依赖于每个文件中相同的架构;但这不是很容易暴露给用户的东西。 (前者只存在于一个PR中)
- 文本为每个字符串按(长度)(数据)块存储,其中长度为4个字节;因此,如果每个文本字符串均为 2 个字节,则它们将在 parquet 数据中存储为 6 个字节,在 CSV 中存储为 3 个字节(因为有逗号)。一种变体编码将长度分开,以便它们可以有效地存储为整数(因为它们都是相同的值,所以工作得非常好)但是 parquet 框架的 none 实际上实现了这个。