R/Python最快读取单体大数据csv文件方案探索
作者:黄天元,复旦大学博士在读,热爱数据科学与开源工具(R),致力于利用数据科学迅速积累行业经验优势和学术知识发现。知乎专栏: R语言数据挖掘 邮箱:huang.tian-yuan@qq.com.欢迎合作交流。
读文件是数据分型在操作上需要完成的第一步,经常用R与Python的用户,对于read.csv和pd.read_csv这些函数应该都不会陌生。但是对于数据量比较大的时候,需要往往需要更加好的方案才能够更快速地读取csv文件。本文就对此进行分析。
R语言比较熟,直接上结论:data.table包的fread函数是读取csv文件最快的包,没有之一。无论多大的csv,它都能够发挥硬件的最大效能,急速读取csv文件。对于单个csv文件而言,已经没有更好的答案。
Python虽然没有那么熟,不过经过探索,最简便的方法是我在 HopeR:R用户学Python:IDE选择与数据导入 提到的:
import pandas as pd
df = pd.DataFrame()
chunksize = 1e6 #这个数字设置多少有待考察
for chunk in pd.read_csv(filename, chunksize=chunksize):
df = df.append(chunk)
思路是,把csv分成多个快,每个块有chucksize那么多的行,先分开读,最后合并到一块。
同时,最近参考了:
认为把这个性能再加速也许也是可能的,因此我们做一个实测性能分析。
话不多说,直接上代码开始进行竞速测试:
1 R语言读取csv的极限速度
为了测试,我们首先构造一个数据集。比较熟悉R语言,还是在R里面构造:
nr_of_rows <- 3e7
df <- data.frame(
Logical = sample(c(TRUE, FALSE, NA), prob = c(0.85, 0.1, 0.05), nr_of_rows, replace = TRUE),
Integer = sample(1L:100L, nr_of_rows, replace = TRUE),
Real = sample(sample(1:10000, 20) / 100, nr_of_rows, replace = TRUE),
Factor = as.factor(sample(labels(UScitiesD), nr_of_rows, replace = TRUE))
print(object.size(df),units = "auto")
这是一个数据框,包括4列,一百万行。最后输出大小,我们看看结果:
在我们的缓存中,它一共占572.2M的内存,我们把它写出。data.table包的fwrite也是同样的优秀,它是写出csv文件最快的函数,没有之一(有新发现的大佬欢迎过来打脸)。
我把这个文件写出到D盘,注意,如果有人希望尝试的话,请保证D盘至少有700M空闲的内存。实测内存大小如图:
672M的csv表格,这就是我们这次要测试的数据。(懒得等,大佬们可以把数据框的行提高上去,来测试更大数据的表现)
那么我们看看R最快的表现:
一秒出点头,不同的时候测试肯定不一样。
题外话:用system.time函数或者microbenchmark包的函数来做也可以,相对的时间是可以比较的。但是这里还是用了比较显式的方法,直接测试时间并求时间差来看时间长短,在Rstudio中要同时运行三行代码才能够达到这种效果。如果不满意,可以直接用system.time函数:
这次更快了,1.19秒。elapsed是我们要看的时间,其他参数的含义,请大家参考: 5 ways to measure running time of R code 。全部代码放下来提供感兴趣的各位使用:
nr_of_rows <- 3e7
df <- data.frame(
Logical = sample(c(TRUE, FALSE, NA), prob = c(0.85, 0.1, 0.05), nr_of_rows, replace = TRUE),
Integer = sample(1L:100L, nr_of_rows, replace = TRUE),
Real = sample(sample(1:10000, 20) / 100, nr_of_rows, replace = TRUE),
Factor = as.factor(sample(labels(UScitiesD), nr_of_rows, replace = TRUE))
print(object.size(df),units = "auto")
library(data.table)
fwrite(df,"D:/df.csv")
Sys.time() -> start
fread("D:/df.csv") -> df
Sys.time() - start
system.time(fread("D:/df.csv") -> df)
应该说,这个速度已经挺快了,基本满足我们的高性能需求。
2 Python高速读取csv
有大佬在早前已经对这个问题进行过探究( https:// medium.com/casual-infer ence/the-most-time-efficient-ways-to-import-csv-data-in-python-cc159b44063d ),其最终结论为:dask.dataframe中的read_csv函数是读取速度最快的函数。
import dask.dataframe as dd