如何从 300GB 文件中提取一列到另一个文件

Posted

技术标签:

【中文标题】如何从 300GB 文件中提取一列到另一个文件【英文标题】:How to extract one column to another file from a 300GB file 【发布时间】:2019-11-12 10:20:22 【问题描述】:

问题在于数据量巨大,我必须使用具有 12GB RAM 的个人笔记本电脑来处理。我尝试了一个 1M 的循环。每一轮都行,并使用 csv.writer。但是 csv.writer 写得像 1M。每两小时排队。那么,还有其他值得尝试的方法吗?

        lines = 10000000
        for i in range(0, 330):
            list_str = []
            with open(file, 'r') as f:
                line_flag = 0
                for _ in range(i*lines):
                    next(f)
                for line in f:
                    line_flag = line_flag + 1
                    data = json.loads(line)['name']
                    if data != former_str:
                        list_str.append(data)
                        former_str = data
                    if line_flag == lines:
                        break
            with open(self.path + 'data_range\\names.csv', 'a', newline='') as writeFile:
                writer = csv.writer(writeFile, delimiter='\n')
                writer.writerow(list_str)
                writeFile.close()

另一个版本

def read_large_file(f):
    block_size = 200000000
    block = []
    for line in f:
        block.append(line[:-1])
        if len(block) == block_size:
            yield block
            block = []

    if block:
        yield block


def split_files():
    with open(write_file, 'r') as f:
        i = 0
        for block in read_large_file(f):
            print(i)
            file_name = write_name + str(i) + '.csv'
            with open(file_name, 'w', newline='') as f_:
                writer = csv.writer(f_, delimiter='\n')
                writer.writerow(block)
            i += 1

这是在它读取一个块并写入之后......我想知道数据传输率为什么保持在 0 左右。

【问题讨论】:

您能否展示您尝试过的代码,该代码需要 2 小时才能处理一百万行? 谢谢,成功了^^ 我会试试 dask。好的起点:examples.dask.org/dataframes/01-data-access.html 你的代码是不必要的O(N^2),因为你反复重读你已经读过的行。打开文件一次,然后一次循环读取 330 行,然后处理该块。另外,我在任何地方都看不到csv.readline;你似乎有一个 JSONL 输入文件。 @Amadan 我尝试了文件内的循环,但我总是得到一个错误,我猜我们在打开文件时无法将数据写入另一个文件? 【参考方案1】:

应该这么简单:

import json
import csv

with open(read_file, 'rt') as r, open(write_file, 'wt', newline='') as w:
    writer = csv.writer(w)
    for line in r:
        writer.writerow([json.loads(line)['name']])

我尝试了文件内的循环,但我总是得到一个错误,我猜我们在打开文件时无法将数据写入另一个文件?

您完全可以在一个文件中写入数据,同时读取另一个文件。不过,在你发布它所说的内容之前,我无法告诉你更多关于你的错误的信息。

您的代码中有一些关于former_str 的内容未包含在“提取一列”中,因此我没有写任何相关内容。

【讨论】:

former_str 用于比较两个字符串是否相同。你的代码完全解决了我的问题!非常感谢!!但我想知道,实际上我的代码读起来很快,只是 csv.writer 太慢了,你知道可能是什么原因吗? “读起来很快,只是 csv.writer 太慢了”——你怎么知道的? 因为我在每个循环中都打印了 i,并在 csv.write 之前和之后打印了一些字符串【参考方案2】:

这样的东西有用吗?

本质上是使用生成器来避免读取内存中的整个文件,并且一次写入一行数据。

import jsonlines  # pip install jsonlines
from typing import Generator

def gen_lines(file_path: str, col_name: str) -> Generator[str]:
    with jsonline.open(file_path) as f:
        for obj in f:
            yield obj[col_name]


# Here you can also change to writing a jsonline again
with open(output_file, "w") as out:
     for item in gen_lines(your_file_path, col_name_to_extract):
         out.write(f"item\n")

【讨论】:

我试过类似这样的版本,但还是一样,阅读没有问题,但是当它开始写时,一个小时内没有反应:/我也添加了上面的代码跨度>

以上是关于如何从 300GB 文件中提取一列到另一个文件的主要内容,如果未能解决你的问题,请参考以下文章

从混合字母和数字列熊猫中提取日期时间

PDO 从表中提取一列到一维数组中

如何从 tsv 文件中提取第一列?

如何使用dplyr mutate从输入一列到返回一个列表的函数中创建新的列?

如何安全地赋予我的功能而不使我的主要形式卡住

从一个文件中提取数据并保存到另一个文件