《高效R语言编程》5-高效输入输出

2021-08-20 10:29:36 浏览数 (1)

在读取一行数据之前,应该先考虑下重复数据管理的通用规则,不改写原始数据。原始文件视为只读,保留原始文件名字并说明来源,是一个好办法。

软件配置

几个包:

代码语言:javascript复制
install.packages(c("rio","readr","data.table","feather","WDI"))

关于数据I/O的高级技巧

  • R语言自己的文件格式是.Rds,可以使用readRDS()与saveRDS()函数导入与导出,是一种速度与空间存储都什么高效的格式。
  • 使用rio包的import()能导入各种格式的数据,避免加载特定格式库的麻烦。
  • 对于高效导入大文本文件,使用readr或data.table与read.table()相当。
  • 使用file.size()与object.size()跟踪文件与R对象的大小,以便在过大之前提前预防。

使用rio的通用数据导入

多功能包,名副其实,提供简单易用和计算高效的函数,其目标是简化数据导入导出过程。R的数据导入导出手册中有些函数已经过时了,比如WriteXLS包,且很难学习。rio包可以处理的格式包含:.csv, .feather, .json, .dta, .xls, .xlsx和谷歌在线表格。其无需指定可选的format参数,另外可以从网络下载数据。json格式的导入还可以使用jsonlite和和geojasonio包。

代码语言:javascript复制
library("rio")

x <- import("mtcars.csv")
y <- import("mtcars.rds")
z <- import("mtcars.dta")

export(mtcars, "mtcars.csv")
export(mtcars, "mtcars.rds")
export(mtcars, "mtcars.xls")

纯文本格式

.csv格式是最常见格式,有三种读入R的方法:1)基础R的read.csv(),2)fread() 里data.table方法3)较新的readr包里read_csv()函数。虽然有所差异,但是交叉兼容。read.csv()是read.delim()和read.table()的封装。readstata13包是专门读取Stata13以上版本的.dta文件而开发的。对于小于1M的数据,read.csv()比read_csv()要快,然而fread()比两个都快,如果是更大的数据,read_csv()和data.table比read.csv()快5倍左右。

fread()与read_csv()的差异

readr与基础read_()一样,是基于前1000行而不是所有行来决定每个变量的类。使用readr的话,会将违规数值转换成NA,而fread()会自动将它认为是数值的列转化成字符,fread()另一特征是可以使用列名或索引来设置select参数,从而有选择的读取列。总的来说,三者在读入数据的差异超过了代码执行的时间,与基础R相比,其他两个的速度提升是一定程度的牺牲健壮性为代价的。在基础R中stringAsFactors=TRUE时才会将字符不转化为因子,而fread()和read_csv()函数默认返回字符型。read_()生成tbl_df类,而fread()产生data.table()类对象,没有实际差别,处理稍有不同,除非trbble包被加载。

R外预处理文本

读入一个4G的文本文件,会耗尽16G的内存RAM,可以使用shell命令split等分割文件,采用数据库是另外一个解决方案。split -b100m bigfile.csv # -b100m意思是分割成100m每个的文件。

二进制文件格式

纯文本格式有局限性,缺少类型安全,限于表格,限制 了数值精度,以二进制保存,可以减少读写时间和文件大小。

R自带的文件格式:Rds和Rdata

save()为Rdata是应用最广泛的,函数功能类似save.img()和save.imge()。saveRDS()函数应用相对较少,作者推荐这个,保存R对象更加简洁,readRDS()更加灵活,结果对象可赋值任何名字。使用这个是个好习惯,强制指定对象名字。

feather文件格式

这是为了R语言与Python程序员协作而设计的格式,速度快,轻量、保存数据框是与语言无关。

二进制文件的基准测试

Rds文件表现最好,磁盘空间仅仅是csv文件的1/4多点,feather格式大约是csv的一半。读入,比read.csv()快十倍左右,写feather更快,比write.csv()快十倍,而saveRDS()仅仅快1.2倍。

Protocol Buffers格式

谷歌的,RProtoBuf包提供了R接口。

从互联网获得数据

download.file()函数和zip()可以批量下载和解压数据。read_csv()也可以直接读取网址中的数据,但是如果下载失败需要重复下载。

代码语言:javascript复制
fileUrl <- "http://www.newcl.org/data/zipfiles/a1.zip"
download.file(fileUrl, destfile = "a1.zip") #下载并保留原始文件名
unzip('a1.zip', exdir="data")
file.remove("1.zip") #移除原文件防止空间浪费

rOpenSci是众多帮助下载和导入数据的包,下面的代码是通过WDI包(不被rOpenSci支持),访问世界银行下载的交通CO2排放的数据:

代码语言:javascript复制
> library("WDI")
> WDIsearch("CO2")
      indicator              name                                                                                                                               
 [1,] "EN.ATM.CO2E.CP.KT"    "CO2 emissions from cement production (thousand metric tons)"                                                                      
 [2,] "EN.ATM.CO2E.EG.ZS"    "CO2 intensity (kg per kg of oil equivalent energy use)"                                                                           
 [3,] "EN.ATM.CO2E.FF.KT"    "CO2 emissions from fossil-fuels, total (thousand metric tons)"                                                                    
 [4,] "EN.ATM.CO2E.FF.ZS"    "CO2 emissions from fossil-fuels (% of total)"                                                                                     
 [5,] "EN.ATM.CO2E.GDP"      "CO2 emissions, industrial (kg per 1987 US$ of GDP)"                                                                               
 [6,] "EN.ATM.CO2E.GF.KT"    "CO2 emissions from gaseous fuel consumption (kt) "                                                                                
 [7,] "EN.ATM.CO2E.GF.ZS"    "CO2 emissions from gaseous fuel consumption (% of total) "                                                                        
 [8,] "EN.ATM.CO2E.GL.KT"    "CO2 emissions from gas flaring (thousand metric tons)"                                                                            
 [9,] "EN.ATM.CO2E.KD.87.GD" "CO2 emissions, industrial (kg per 1987 US$ of GDP)"          
CO2_transport <- WDI(indicator = "EN.CO2.TRAN.ZS") 
> head(CO2_transport)
  iso2c    country EN.CO2.TRAN.ZS year
1    1A Arab World             NA 2020
2    1A Arab World             NA 2019
3    1A Arab World             NA 2018
4    1A Arab World             NA 2017
5    1A Arab World             NA 2016
6    1A Arab World             NA 2015

最好在代码中对数据来源做些简单注释,方便代码对自己和他人的可用性。与Web页面交互的两个包是httr和RCurl包,httr有相对友好的用户接口(没有图形界面的),RCurl是更接近底层。

访问包中的数据

示例数据可以用如下方式查看:data(package="dplyr")

代码语言:javascript复制
Data sets in package ‘dplyr’:

band_instruments                Band membership
band_instruments2               Band membership
band_members                    Band membership
starwars                        Starwars characters
storms                          Storm tracks data

原始数据通常位于R包的extdata目录中,system.file()函数输出具体包的文件路径:

代码语言:javascript复制
> list.files(system.file("extdata",package="readr"))
[1] "challenge.csv"     "epa78.txt"         "example.log"       "fwf-sample.txt"    "massey-rating.txt"
[6] "mtcars.csv"        "mtcars.csv.bz2"    "mtcars.csv.zip"   

可以通过下图的方式,按tab键就可以查看文件夹结构:

0 人点赞