使用 Pandas 或其他方法比较大型 (~40GB) 文本数据

Posted

技术标签:

【中文标题】使用 Pandas 或其他方法比较大型 (~40GB) 文本数据【英文标题】:Comparing large (~40GB) of textual data using Pandas or an alternative approach 【发布时间】:2017-06-07 19:28:26 【问题描述】:

我有大量 csv 数据,我需要处理大约 40GB 的大小(我们称之为“主体”)。此正文中每个文件中的数据由单列 CSV 文件组成。每行是一个由单词和短句组成的关键字,例如

Dog
Feeding cat
used cars in Brighton
trips to London
.....

需要将此数据与另一组文件(这个大小为 7GB,我将其称为“删除”)进行比较,需要识别删除中的任何关键字并将其从正文中删除。移除的数据与正文中的数据相似,即:

Guns
pricless ming vases
trips to London
pasta recipes
........

虽然我有一种方法可以完成工作,但这是一种非常缓慢的方法,可能需要一周的时间才能完成。这是一种多线程方法,其中 7GB 正文中的每个文件都在 for 循环中与正文中的文件进行比较。它将 Removals 文件中的列转换为列表,然后过滤正文文件以保留不在该列表中的任何行。然后将过滤后的数据附加到输出文件中:

def thread_worker(file_):


    removal_path="removal_files"
    allFiles_removals = glob.glob(removal_path + "/*.csv", recursive=True)
    print(allFiles_removals)

    print(file_)
    file_df = pd.read_csv(file_)

    file_df.columns = ['Keyword']

    for removal_file_ in allFiles_removals:

        print(removal_file_)
        vertical_df = pd.read_csv(vertical_file_, header=None)

        vertical_df.columns = ['Keyword']

        vertical_keyword_list = vertical_df['Keyword'].values.tolist()

        file_df = file_df[~file_df['Keyword'].isin(vertical_keyword_list)]


    file_df.to_csv('output.csv',index=False, header=False, mode='a')

显然,我的主要目标是找出如何更快地完成这项工作。Pandas 是不是最好的方法?在处理 CSV 文件时,我倾向于默认使用它。

【问题讨论】:

你想比较什么?一个文件中的所有数据与另一个文件中的所有数据对比? 更准确的说法是我想要获取一组文件(总共 40GB),并且我想要删除也出现在另一组文件(7GB 正文)中的所有关键字。跨度> 我会将主体拆分为多个块,例如每个 1GB,然后根据您的 RAM 大小在每个块上并行执行其余部分。然后转换一个块(使用awk),使其每行一个单词,并引入一个 NUL 和另一个唯一字符来标记行的开始和结束。然后对块运行grep -vfb 的删除。然后重新组装。 这不是minimal reproducible example(还)。 你能改变数据集吗?排序它,即?还是保存位置、排序和恢复位置?我只是想提出一点,然后我们谈论的是 40GB 的单词——主要是关于算法的效率——而不是比较 panda 和纯 cvs。 【参考方案1】:

IIUC 你可以这样做:

# read up "removal"  keywords from all CSV files, get rid of duplicates
removals = pd.concat([pd.read_csv(f, sep='~', header=None, names=['Keyword']) for f in removal_files]
                     ignore_index=True).drop_duplicates()


df = pd.DataFrame()
for f in body_files:
    # collect all filtered "body" data (file-by-file)
    df = pd.concat([df,
                    pd.read_csv(f, sep='~', header=None, names=['Keyword']) \
                      .query('Keyword not in @removals.Keyword')],
                   ignore_index=True)

【讨论】:

这是一个很好的方法,但缺点是在将所有文件加载到其中时会耗尽内存...... @GreenGodot,你有什么限制?有多少 RAM 可供您使用?【参考方案2】:

您可能可以分小块阅读它们,并将文本列作为类别以在阅读时删除重复项

从 pandas.api.types 导入 CategoricalDtype

TextFileReader = pd.read_csv(path, chunksize=1000, dtype = "text_column":CategoricalDtype) # 每块的行数

dfList = [] 对于 TextFileReader 中的 df: dfList.append(df)

df = pd.concat(dfList,sort=False)

【讨论】:

以上是关于使用 Pandas 或其他方法比较大型 (~40GB) 文本数据的主要内容,如果未能解决你的问题,请参考以下文章

Python Pandas 改进了目前需要约 400 分钟运行的大型数据集的计算时间

使用 Pandas 读取大型文本文件 [重复]

head

Pandas groupby nlargest sum

text [处理大型数据集]使用chunksizes控制大型数据集(无内存错误)#pandas

Pandas:修复数据框中键的拼写错误