查看原文
其他

R:在几十种计量软件之间转换数据格式-rio

连享会 连享会 2023-10-24

👇 连享会 · 推文导航 | www.lianxh.cn

连享会 · 2022 暑期班

作者: 温世彬 (中国农业大学)
邮箱: shibin_wen@163.com

温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」。或直接长按/扫描如下二维码,直达原文:


目录

  • 1. 简介

  • 2. rio 包支持的文件格式

  • 3. rio 包安装

  • 4. rio 包导出数据:export()

  • 5. rio 包导入数据:import()

  • 6. rio 包转换数据:convert()

  • 7. rioweb:基于 Web 的 rio 包接口

  • 8. 结语

  • 9. 参考资料

  • 10. 相关推文



1. 简介

瑞士军刀是一款瑞士军队配备过的袖珍工具刀,其特点是 工具齐全、设计精巧、方便实用。瑞士军刀通常整合了主刀、小刀、铰剪、开瓶器、木锯、小改锥、拔木塞钻、牙签、小镊子等系列工具,适合旅行、登山、垂钓、汽车及自行车修理等多种情况,应用广泛,极受欢迎。

rio R 包:一款数据 input/output 的瑞士军刀

rio 包由 Thomas J.Leeper 开发,其目的是通过实现瑞士军刀风格的四个简单函数,使得 R 中数据文件的导入和导出尽可能简单。R 作为一款开源语言,在 rio 包之前,导入或者导出不同格式的数据往往需要调用不同的 package 进行组合。针对不同文件类型,常用的 R package 和函数如下:

  • readxl 包:读取常用的 excel 文件,比如 xls,xlsx 等;
  • writexl 包:输出 excel 文件;
  • openxlsx 包:读取、输出 xlsx 格式文件;
  • haven 包:读取 SPSS(sav),Stata(dta)、SAS(sav7bdat)统计软件格式的数据;
  • readr 包:快速读取文本表格的格式数据,比如 csv,tsv,fwf 等格式;
  • DBI 包:连接大部分主流关系型数据库,比如 PostgreSQL,SQL Server,Oralce,MySQL,SQLite 等;
  • jsonlite 包:读取 json 格式数据文件;
  • xml2 包:读取 HTML 和 XML 格式数据;
  • httr 包:Web APIs,从网站开放的 API 中读取数据;
  • rvest 包:读取并解析 HTML 网页数据;
  • webreadr 包:读取常见的 Web 日志格式数据;
  • vroom 包:实现读取矩形数据,部分功能类似 readr、data.table,但速度更快。

想要在 R 语言中导入导出不同的数据格式,可能需要调入上述各种包进行转换,既麻烦又占用内存,往往对于新手在进行数据处理分析时就极易容易卡在数据导入的第一步环节上。那么有没有一款高效好用且全面的R包可以简化导入导出数据过程呢?这个过程往往对新入手 R 的用户来说是不必要且复杂的。rio 包将上述过程统一为两个简单的函数 import()export(),并且能够通过 convert() 函数实现几十种计量软件之间转换数据格式。

2. rio 包支持的文件格式

rio 支持几十种数据文件格式的导入和导出,支持格式的完整列表如下:

格式对应扩展名导入包导出包默认安装
逗号分隔数据.csvdata.tabledata.table
管道分隔数据.psvdata.tabledata.table
制表符分隔数据.tsvdata.tabledata.table
CSVY (CSV + YAML metadata header).csvydata.tabledata.table
SAS.sas7bdathavenhaven
SPSS.savhavenhaven
SPSS (compressed).zsavhavenhaven
Stata.dtahavenhaven
SAS XPORT.xpthavenhaven
SPSS Portable.porhaven
Excel.xlsreadxl
Excel.xlsxreadxlopenxlsx
R syntax.Rbasebase
保存的 R 对象.RData, .rdabasebase
序列化的 R 对象.rdsbasebase
Epiinfo.recforeign
Minitab.mtpforeign
Systat.sydforeign
“XBASE” 数据库文件.dbfforeignforeign
Weka 属性关系文件格式.arffforeignforeign
数据交换格式.difutils
Fortran data没有可识别的扩展名utils
固定宽度格式数据.fwfutilsutils
gzip 逗号分隔数据.csv.gzutilsutils
Apache Arrow (Parquet).parquetarrowarrow
EViews.wf1hexView
Feather R/Python 交换格式.featherfeatherfeather
Fast Storage.fstfstfst
JSON.jsonjsonlitejsonlite
Matlab.matrmatiormatio
OpenDocument Spreadsheet.odsreadODSreadODS
HTML.htmlxml2xml2
Shallow XML documents.xmlxml2xml2
YAML.ymlyamlyaml
Clipboard默认值为 tsvcliprclipr
Google Sheets作为逗号分隔的数据


Graphpad Prism.pzfxpzfxpzfx

3. rio 包安装

第一次运行的时候建议增加运行一条命令:install_formats(),会安装相关格式依赖的包,确保 rio 支持扩展到所需导入和导出格式。

install.packages("rio")
install_formats() 

可以使用以下方式安装 GitHub 上的最新开发版本:

if (!require("remotes")){
    install.packages("remotes")
}
remotes::install_github("leeper/rio")

4. rio 包导出数据:export()

为了便于获取读取的数据集,本文先从导出数据开始展示。export() 函数语法如下:

export(x, file, format, ...)

export() 函数有三个参数:

  • x:要写入文件的数据框架或矩阵;
  • file:文件名,必须指定文件和/或格式;
  • format:包含文件格式的可选字符串,可用于覆盖从文件推断出的格式,或者创建一个符号名称为x并指定文件扩展名的文件,而不是指定文件。如果由于某种原因文件没有扩展名,或者文件扩展名与其实际类型不匹配,则可以手动指定文件格式以覆盖格式推断步骤。

在实际使用中,大多只需要提供前两个参数,即想要导出的数据和指定导出路径下的文件名。为了演示,本文使用的数据集是 tidyr 包中自带的 who 数据,具体如下:

# 设置路径
setwd("C:/Users/Desktop/rio"

# 加载包
library(rio)
library(tidyr)
tidyr::who

> tidyr::who
# A tibble: 7,240 × 60
   country     iso2  iso3   year new_sp_m014 new_sp_m1524 new_sp_m2534 new_sp_m3544 new_sp_m4554 new_sp_m5564
   <chr>       <chr> <chr> <int>       <int>        <int>        <int>        <int>        <int>        <int>
 1 Afghanistan AF    AFG    1980          NA           NA           NA           NA           NA           NA
 2 Afghanistan AF    AFG    1981          NA           NA           NA           NA           NA           NA
 3 Afghanistan AF    AFG    1982          NA           NA           NA           NA           NA           NA
 4 Afghanistan AF    AFG    1983          NA           NA           NA           NA           NA           NA
 5 Afghanistan AF    AFG    1984          NA           NA           NA           NA           NA           NA
 6 Afghanistan AF    AFG    1985          NA           NA           NA           NA           NA           NA
 7 Afghanistan AF    AFG    1986          NA           NA           NA           NA           NA           NA
 8 Afghanistan AF    AFG    1987          NA           NA           NA           NA           NA           NA
 9 Afghanistan AF    AFG    1988          NA           NA           NA           NA           NA           NA
10 Afghanistan AF    AFG    1989          NA           NA           NA           NA           NA           NA
# … with 7,230 more rows, and 50 more variables: new_sp_m65 <int>, new_sp_f014 <int>, new_sp_f1524 <int>,
#   new_sp_f2534 <int>, new_sp_f3544 <int>, new_sp_f4554 <int>, new_sp_f5564 <int>, new_sp_f65 <int>,
#   new_sn_m014 <int>, new_sn_m1524 <int>, new_sn_m2534 <int>, new_sn_m3544 <int>, new_sn_m4554 <int>,
#   new_sn_m5564 <int>, new_sn_m65 <int>, new_sn_f014 <int>, new_sn_f1524 <int>, new_sn_f2534 <int>,
#   new_sn_f3544 <int>, new_sn_f4554 <int>, new_sn_f5564 <int>, new_sn_f65 <int>, new_ep_m014 <int>,
#   new_ep_m1524 <int>, new_ep_m2534 <int>, new_ep_m3544 <int>, new_ep_m4554 <int>, new_ep_m5564 <int>,
#   new_ep_m65 <int>, new_ep_f014 <int>, new_ep_f1524 <int>, new_ep_f2534 <int>, new_ep_f3544 <int>, …

导出常用的几种数据格式:

export(who, "who.xlsx")      # 导出 Excel 格式 
export(who, "who.csv")       # 导出 CSV 格式
export(who, "who.rds")       # 导出 R 数据格式
export(who, "who.RData")     # 导出 R 存储空间
export(who, "who.dta")       # 导出 Stata 数据格式
export(who, "who.sav")       # 导出 SPSS 数据格式
export(who, "who.sas7bdat")  # 导出 SAS 数据格式
export(who, "who.json")      # 导出 JSON 数据格式
export(who, "who.mat")       # 导出 Matlab 数据格式

rio 的一个特别有用的功能是能够从压缩(例如,zip)目录导入和导出,为用户节省压缩大型导出文件的额外步骤,例如:

export(who, "who.tsv.zip")  # 压缩文件为 zip
export(who, "who.csv.gz")   # 压缩文件为 gzip

rio v0.5.0 开始,还可以将多个数据框写入 Excel 工作簿或 HTML 文件的相应工作表:

# 创建一个简单列表并命名
rio_list <- list(who = who, iris = iris, mtcars = mtcars)

# 使用 export() 函数将三个 list 导出至 Excel 的三个 sheet 中
export(rio_list, file = "rio_list.xlsx"

5. rio 包导入数据:import()

rio 允许用户使用一个(通常是单参数)函数以几乎任何格式导入文件。从文件扩展名推断文件格式,并为用户调用相应的数据导入函数,最终返回一个简单的数据框 data.frame。用户仅需记住一个函数名 import()。其语法如下:

import(file, format, setclass, which, ...)

import() 函数在 export() 函数基础上多增加了两个参数:

  • setclass:设置类别,默认为 data.frame,可以另外设置"tbl","tbl_df"。
  • which:其主要控制从多对象文件中导入数据。

但在实际使用中,大多只需要提供一个参数 file ,即需要导入数据完整的路径名称。此外,建议将 setclass 设置为 tibble 数据框格式会更为方便。本文继续以之前导出的不同格式的 who 数据进行演示:

导入csv文件:

import("who.csv")  # 不加任何参数是 data.frame 格式

import("who.csv", setclass = "tbl_df"# 加入 setclass 可以直接读取 tibble 数据框格式

导入 Stata 数据:

import("who.dta", setclass = "tbl_df")

导入 Excel 数据:

import("who.xlsx", setclass = "tbl_df")

导入 R 数据或 R 工作空间:

import("who.rds", setclass = "tbl_df")

import("who.rdata", setclass = "tbl_df")

导入 SPSS 数据

import("who.sav", setclass = "tbl_df")

导入 JSON 数据

import("who.json", setclass = "tbl_df") %>% 
  as_tibble()   # setclass 不能直接转为 tibble 数据框,加一个 as_tibble() 进行转换

导入 Matlab 数据

import("who.mat", setclass = "tbl_df")

可以看到,无论是导出还是导入数据,使用 rio 包十分简便且容易理解,不需要调用其他 R 包被或者记一堆 R 包内相似的函数就能够对主流的计量软件数据格式进行操作。与 import() 函数类似的还有一个基于列表的导入函数:import_list()。其允许用户从多对象文件(如 Excel,Rdata、zip 或 HTML 文件等) 导入数据框列表,具体用法可以在 RStudio 中输入 ?import_list 查看帮助文档。

在帮助文档中可以看到 rio 包是封装了不同数据导入和导出的包,如果需要对导入或者导出的数据进行更精细的操作,则可以根据 rio 调用的不同包查看帮助文档并使用对应包命令的参数。比如读取 Stata 数据时,在使用 import() 函数时可知,rio 调用的是 haven 包的 read_dta() 函数进行读取。我们进一步查看haven::read_dta 帮助文档,可以发现其用法如下:

read_dta(
  file,
  encoding = NULL,
  col_select = NULL,
  skip = 0,
  n_max = Inf,
  .name_repair = "unique"
)

因此,结合 import()haven::read_dta() 函数,可以对之前读取 Stata 的代码进行调整,比如只读取数据的前 4 列和前 5 行,可以修改如下:

import("who.dta", setclass = "tbl_df",
       col_select = 1:4, n_max = 5,
       encoding = "utf-8" )  # 读取 1-4 列,前 5 行数据

比如,输入 col_select= 1:4 后,import() 会在调用 haven 包时将其传给 read_dta(),其他同理。同样,其他格式数据导入如果需要做更精细化导入处理也可参照同样的思路添加参数。

6. rio 包转换数据:convert()

rio 包最重要的一个功能是实现不同数据格式之间的快速转换,使用的是 convert() 函数,通过从导入的文件构造一个数据框架并立即将其写回磁盘来链接 import()export() 两个函数。convert() 以不可见的方式返回导出文件的文件名,以便可以使用它以编程方式访问新文件。其语法如下:

convert(in_file, out_file, in_opts = list(), out_opts = list())

convert()有四个参数:

  • in_file:输入文件名
  • out_file:输出文件名
  • in_opts:通过 inport() 传递的文件名列表选项
  • out_opts:通过 output() 传递的文件名列表选项

下面继续使用 who 数据进行演示,将不同格式的 who 数据均转换为 Stata 的 dta 格式,为了区别,在导出的文件名前均加入前缀 XX2dta_

# 将 csv 文件转换为 dta
convert(in_file = "who.csv", out_file = "csv2dta_who.dta")

# 将 xlsx 文件转换为 dta
convert(in_file = "who.xlsx", out_file = "xlsx2dta_who.dta")

# 将 zip 文件转换为 dta
convert(in_file = "who.tsv.zip", out_file = "zip2dta_who.dta")

# 将 sav 文件转换为 dta
convert(in_file = "who.sav", out_file = "sav2dta_who.dta")

# 将 rds 转换为 dta
convert(in_file = "who.rds", out_file = "rds2dta_who.dta")

在使用 convert() 时,我们可以通过 in_optsout_opts 控制 import()out_opt() 选项的参数,实时读取文件的同时并将其保存。这对于将其他参数传递给导入或导出方法非常有用。例如,这对于读取固定宽度格式的文件( fwf 格式)并将其转换为逗号分隔值文件可能很有用:

# 写入 fwf 文档内容
cat(file = "fwf.fwf""123456""987654", sep = "\n")
# 将 fwf 文本转换为 csv 文档
convert("fwf.fwf""fwf.csv", in_opts = list(widths = c(123)))
# 读取数据
import("fwf.csv", setclass = "tbl_df"
# A tibble: 2 × 3
     V1    V2    V3
  <int> <int> <int>
1     1    23   456
2     9    87   654

rio 包的 convert() 对数据转换基本可以一步到位,实现不同数据格式之间的无缝切换。如果之前的包,大致转换数据的流程(以 xlsx → dta 格式为例),调入读取 csv 相关的包 → 读取 csv 格式数据 → 调入输出 Stata 数据的包 → 输出 dta 格式数据:

library(readxl) # 加载 readxl 包
readxl::read_xlsx("who.xlsx") -> df # 导入 Excel 数据
library(haven) # 加载 haven 包
df %>% 
  write_dta("who.dta"# 导出 Stata 数据

或者简洁一点的方式:

pacman::p_load(readxl, haven) # 加载包
readxl::read_xlsx("who.xlsx") %>% 
  haven::write_dta("who.dta"# 导入数据再输出数据进行转换

再对比rio包的转换方式:

rio::convert("who.xlsx""who.dta")

显然,使用 rioconvert() 函数进行数据格式转换会更简单一些,只需要修改数据的拓展名。

7. rioweb:基于 Web 的 rio 包接口

不会使用 R 也想实现数据格式之间的转换呢?Luca Braglia (2018) 开发了一款名为 rioweb 的Shiny 应用,搭建了一个基于 Web 能够与 rio R 包连接的接口,即可以通过浏览器访问 rio 实现文件转换功能。其访问网址:https://gallery.shinyapps.io/rioweb/

目前 rioweb 主要支持 Comma separated,Excel,JSON,R,SAS,SPSS,Stata 和 Tab separated 几种格式之间的转换,基本满足了主流计量软件的数据存储格式。使用方法只需简单点击 Browse 上传需要转换的文件 → 再选择 Output format 中需要转换的格式 → 最后点击 Download 下载数据即可。无需安装任何软件也可以实现数据之间的格式转换。

8. 结语

本推文较为详细地介绍了 R 语言中 rio 包的使用,其封装了主流计量软件数据包,可以支持几十种数据格式的转换。以往的数据导入导出方式可能需要针对每一种特定数据格式调用相对应的一种包,对于新手学习来说极为不便,代码略显啰嗦。但是使用了 rio 后,可以不需要记住繁琐的包名即可实现相应功能,用 R 包开发者 Thomas J. Leeper 的描述就是 “to make data file I/O in R as easy as possible”。

9. 参考资料

  • Package rio. -PDF-

  • rio: A Swiss-Army Knife for Data I/O. -Link-

  • Import, Export, and Convert Data Files. -Link-

  • Bruno Rodrigues. Modern R with the tidyverse[M], 2022. -Link-

10. 相关推文

Note:产生如下推文列表的 Stata 命令为:
lianxh 数据导入 数据导出 数据转换, m
安装最新版 lianxh 命令:
ssc install lianxh, replace

  • 专题:Stata教程
    • Stata-Python交互-9:将python数据导入Stata
    • Stata-Python交互-8:将Stata数据导入Python
  • 专题:数据处理
    • Stata:时间序列数据转换-tstransform
    • Stata数据处理:一月有几周?月度和周数据转换
    • Stata数据处理:FRED数据导入问题的解决方案

课程推荐:因果推断实用计量方法
主讲老师:丘嘉平教授
🍓 课程主页https://gitee.com/lianxh/YGqjp

New! Stata 搜索神器:lianxhsongbl  GIF 动图介绍
搜: 推文、数据分享、期刊论文、重现代码 ……
👉 安装:
. ssc install lianxh
. ssc install songbl
👉  使用:
. lianxh DID 倍分法
. songbl all

🍏 关于我们

  • 连享会 ( www.lianxh.cn,推文列表) 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • 直通车: 👉【百度一下: 连享会】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存