首页 > > > 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那么多的行,先分开读,最后合并到一块。
同时,最近参考了:
https://medium.com/casual-inference/the-most-time-efficient-ways-to-import-csv-data-in-python-cc159b44063d认为把这个性能再加速也许也是可能的,因此我们做一个实测性能分析。
话不多说,直接上代码开始进行竞速测试:
为了测试,我们首先构造一个数据集。比较熟悉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)应该说,这个速度已经挺快了,基本满足我们的高性能需求。
有大佬在早前已经对这个问题进行过探究(https://medium.com/casual-inference/the-most-time-efficient-ways-to-import-csv-data-in-python-cc159b44063d),其最终结论为:dask.dataframe中的read_csv函数是读取速度最快的函数。
import dask.dataframe as dd
import time
start = time.time()
df = dd.read_csv("D:/df.csv")
end = time.time()
print(end - start)我们看看结果:

0.02秒,可怕的速度。
R中csv最强单体导入函数为fread,性能不错。不过Python的dark.data.frame.read_csv更为恐怖,在多线程的硬件条件下连0.1秒都不到就可以快速读入数据。
D盘根目录下现在多了df.csv这个文件,可以手动删除,也可以在R中直接进行管理:
file.remove("D:/df.csv")如果函数返回TRUE,那么说明我们已经成功把创建的文件删除掉了。
原文作者:;如有侵权,请联系管理员删除。