如何在python中读取一个大的tsv文件并将其转换为csv

Posted

技术标签:

【中文标题】如何在python中读取一个大的tsv文件并将其转换为csv【英文标题】:How to read a large tsv file in python and convert it to csv 【发布时间】:2019-08-01 07:44:00 【问题描述】:

我有一个较大的 tsv 文件(大约 12 GB),我想将其转换为 csv 文件。对于较小的tsv 文件,我使用以下代码,它可以工作但速度很慢:

import pandas as pd

table = pd.read_table(path of tsv file, sep='\t')
table.to_csv(path andname_of csv_file, index=False)

但是,此代码不适用于我的大文件,并且内核在中间重置。

有什么办法可以解决这个问题吗?有谁知道这个任务是否可以用 Dask 而不是 Pandas 来完成?

我使用的是 Windows 10。

【问题讨论】:

您在使用基于 unix 的系统吗? 如果是,您可以使用以下命令:tr '\t' ',' <input.tsv >output.csv , 可以由另一个字段分隔符更改 我在 Windows 10 上工作。你的第二条评论我不清楚 如果我们已经回答了您的问题,您能否接受以下详细信息:***.com/help/someone-answers 【参考方案1】:

您可以逐行读取并逐行处理,而不是一次将所有行加载到内存中:

Python 3.x:

fs=","
table = str.maketrans('\t', fs)
fName = 'hrdata.tsv'
f = open(fName,'r')

try:
  line = f.readline()
  while line:
    print(line.translate(table), end = "")
    line = f.readline()

except IOError:
  print("Could not read file: " + fName)

finally:
  f.close()

输入(hrdata.tsv):

Name    Hire Date       Salary  Sick Days remaining
Graham Chapman  03/15/14        50000.00        10
John Cleese     06/01/15        65000.00        8
Eric Idle       05/12/14        45000.00        10
Terry Jones     11/01/13        70000.00        3
Terry Gilliam   08/12/14        48000.00        7
Michael Palin   05/23/13        66000.00        8

输出:

Name,Hire Date,Salary,Sick Days remaining
Graham Chapman,03/15/14,50000.00,10
John Cleese,06/01/15,65000.00,8
Eric Idle,05/12/14,45000.00,10
Terry Jones,11/01/13,70000.00,3
Terry Gilliam,08/12/14,48000.00,7
Michael Palin,05/23/13,66000.00,8

命令:

python tsv_csv_convertor.py > new_csv_file.csv

注意:

如果您使用 Unix 环境,只需运行以下命令:

tr '\t' ',' <input.tsv >output.csv

【讨论】:

【参考方案2】:

如果我错了,请纠正我,但 TSV 文件基本上是 CSV 文件,使用制表符而不是逗号。为了在 python 中有效地翻译它,您需要遍历源文件的行,用逗号替换制表符,并将新行写入新文件。您不需要使用任何模块来执行此操作,用 Python 编写解决方案实际上非常简单:

def tsv_to_csv(filename):
    ext_index = filename.rfind('.tsv')
    if ext_index == -1:
        new_filename = filename + '.csv'
    else:
        new_filename = filename[:ext_index] + '.csv'

    with open(filename) as original, open(new_filename, 'w') as new:
        for line in original:
            new.write(line.replace('\t', ','))

    return new_filename

像这样遍历行只会将每一行一一加载到内存中,而不是将整个内容加载到内存中。不过,处理 12GB 的数据可能需要一段时间。

更新: 事实上,现在我想起来了,在这么大的文件上使用二进制 I/O 可能会快得多,然后在文件的大块上一次用逗号替换制表符。此代码遵循该策略:

from io import FileIO

# This chunk size loads 1MB at a time for conversion.
CHUNK_SIZE = 1 << 20


def tsv_to_csv_BIG(filename):
    ext_index = filename.rfind('.tsv')
    if ext_index == -1:
        new_filename = filename + '.csv'
    else:
        new_filename = filename[:ext_index] + '.csv'

    original = FileIO(filename, 'r')
    new = FileIO(new_filename, 'w')
    table = bytes.maketrans(b'\t', b',')

    while True:
        chunk = original.read(CHUNK_SIZE)
        if len(chunk) == 0:
            break
        new.write(chunk.translate(table))

    original.close()
    new.close()
    return new_filename

在我使用 1GB TSV 文件的笔记本电脑上,第一个函数需要 4 秒才能转换为 CSV,而第二个函数需要 1 秒。如果您的存储能够跟上,调整 CHUNK_SIZE 参数可能会加快速度,但 1MB 对我来说似乎是最佳选择。

使用另一个答案中提到的tr 对我来说需要 3 秒,因此分块 python 方法似乎最快。

【讨论】:

【参考方案3】:

您可以使用Python内置的readwrite逐行重写文件。这可能需要一些时间来处理,具体取决于您的文件大小,但它不应该耗尽内存,因为您正在逐行工作。

with open("input.tsv", "r") as input_file:
    for line in input_file:
        with open("output.csv", "a") as output:
            line = line.replace("\t", ",")
            output.write(line)

【讨论】:

这个答案应该可以工作,但它不必要地打开和关闭输入中每一行的输出文件,如果输入为 12GB 大,这可能会发生很多。这可能会减慢很多。最好在 for 循环之外打开输出文件,并使用模式 'w' 而不是 'a'。通过这些更改,您的答案基本上与我的相同。 我同意。我写我的代码试图尽可能地可读,因为 OP 似乎没有任何直接通过 Python 操作文本文件的知识。如果他觉得有必要,他可以稍后考虑优化代码,或者他可以让它运行一段时间,因为他现在只需要这个特定文件。【参考方案4】:

您可以使用chunksize 分段遍历整个文件。注意这里使用.read_csv() 而不是.read_table()

df = pd.DataFrame()
for chunk in pd.read_csv('Check1_900.csv', header=None, names=['id', 'text', 'code'], chunksize=1000):
    df = pd.concat([df, chunk], ignore_index=True)

source


您也可以试试low_memory=False 标志 (source)。


接下来是memory_map(向下滚动到https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

memory_map : bool,默认为 False

如果为 filepath_or_buffer 提供了文件路径,则将文件对象直接映射到内存并直接从那里访问数据。使用此选项可以提高性能,因为不再有任何 I/O 开销。

请注意,to_csv() 具有类似的功能。

【讨论】:

以上是关于如何在python中读取一个大的tsv文件并将其转换为csv的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中解析非常大的文件?

如何将压缩的 TSV 文件读取到 Databricks 上的数据框?

如何读取大的avro文件,并将整个文件加载到内存中。

python 模块化 处理大文件 tsv csv

如何导入 .tsv 文件

将 json 对象数组转换为 tsv (python)