在不加载完整内容的情况下找出 csv 行数的最佳方法

Not*_*ame 2 python csv pandas

最近几天我在工作中处理了大量 4-5 Gb 的 csv 文件,因此我知道它们通过读/写取得了多少进展,我在 pandas 的方法之上编写了几个包装函数。这一切似乎都运行得很好,虽然有一点开销,但便利性胜过大多数问题。

同时,在读取 csv 时,为了让进度条显示正确的百分比,我需要提前知道行数,因为这决定了有多少块。我想出的最简单的解决方案是简单地加载 csv 的第 0 列,然后开始加载其余部分并获取其大小。但是,当您拥有数百万行大小的文件时,这确实需要一些时间。

此外,读取单列所花费的总时间比例过高:读取 125 列、几百万行的 csv 中的单列大约需要 24 秒,读取整个文件则需要 63 秒。

这是我一直用来读取 csv 的函数:

def read_csv_with_progressbar(filename: str,
                              chunksize: int = 50000) -> pd.DataFrame:

    length = pd.read_csv(filename, usecols=[0])
    length = length.values.shape[0]

    total = length//chunksize
    chunk_list = []

    chunks = pd.read_csv(filename, chunksize=chunksize)
    with tqdm(total=total, file=sys.stdout) as pbar:
        for chunk in chunks:
            chunk_list.append(chunk)
            pbar.set_description('Reading source csv file')
            pbar.update(1)

        df = pd.concat([i for i in chunk_list], axis=0)

    return df

Run Code Online (Sandbox Code Playgroud)

有什么方法可以比使用我有缺陷的方法更快地获取 csv 中的行数?

orl*_*rlp 5

假设 CSV 文件中没有带引号的字符串(其中包含换行符)或其他恶作剧,一个准确(但很黑客)的解决方案是甚至不解析文件,而只是计算文件中换行符的数量:

chunk = 1024*1024   # Process 1 MB at a time.
f = np.memmap("test.csv")
num_newlines = sum(np.sum(f[i:i+chunk] == ord('\n'))
                   for i in range(0, len(f), chunk))
del f
Run Code Online (Sandbox Code Playgroud)

  • @pavel 如果您想要以牺牲准确性为代价获得更快的速度,您可以在文件中半随机地采样 50MB 的数据,并将其线性外推到整个文件。 (3认同)