将 SAS sas7bdat 数据读入 R
Read SAS sas7bdat data into R
R 有哪些选项可以将原生 SAS 格式的文件 sas7bdat
读取到 R 中?
1997-98 年来自 LEA Universe 的 NCES Common Core, for example, contains an extensive repository of data files saved in this format. For concreteness, let's focus on trying to read in this 文件,其中包含从 A 到 I 的所有州的实体的教育机构级别人口统计数据。
这是来自 SAS 的数据预览:
将这些数据引入我的 R 环境的最简单方法是什么?我没有任何可用的 SAS 版本,也不愿意付费,所以简单地将其转换为 .csv 会很麻烦。
问题
问题似乎是您尝试使用的文件格式不正确。具体来说,空白单元格未编码(R
使用 NA
),而只是留空。当尝试加载制表符分隔的文件时,这会给 R 带来问题,它认为列数不正确。
使用 SAS 文件的解决方法
我找到了一个解决方法,使用 sas7bdat
包加载 SAS 文件,然后将空白单元格 (""
) 重新编码为 NA:
install.packages("sas7bdat")
require("sas7bdat")
download.file("http://nces.ed.gov/ccd/Data/zip/ag121a_supp_sas.zip",
destfile = "sas.zip")
unzip("sas.zip")
sas <- read.sas7bdat(file = "ag121a_supp.sas7bdat", debug = FALSE)
sas[sas == ""] <- NA
不过,此方法有两个问题需要注意:
- 速度很慢(查看评论)
sas7bdat
包在其作者撰写本文时目前被认为是实验性的。因此它可能不会加载所有 sas 文件,我会在使用前彻底检查它所做的不一致。
非 R 解决方案
它不完全规范,但您也可以下载制表符分隔的文件,在 LibreOffice Calc 中打开它们(Microsoft Excel 似乎搞砸了),然后通过搜索 ""
并替换为 NA
.
sas7bdat
除了我正在查看的一个文件(具体来说,this one)以外的所有文件都工作正常;在向 sas7bdat
开发人员 Matthew Shotwell 报告错误时,他还向我指出了 Hadley 在 R 中的 haven
包的方向,它也有一个 read_sas
方法。
这种方法的优越性有两个原因:
1) 读取上面链接的文件没有任何问题
2) 它比 read.sas7bdat
快 much(我说的是 much)。这是一个快速基准(在 this 文件上,比其他文件小)作为证据:
microbenchmark(times=10L,
read.sas7bdat("psu97ai.sas7bdat"),
read_sas("psu97ai.sas7bdat"))
Unit: milliseconds
expr min lq mean median uq max neval cld
read.sas7bdat("psu97ai.sas7bdat") 66696.2955 67587.7061 71939.7025 68331.9600 77225.1979 82836.8152 10 b
read_sas("psu97ai.sas7bdat") 397.9955 402.2627 410.4015 408.5038 418.1059 425.2762 10 a
没错——haven::read_sas
比 sas7bdat::read.sas7bdat
少 99.5% 的时间。
次要更新
我以前无法弄清楚这两种方法是否产生了相同的数据(即,两者在读取数据方面具有相同的保真度),但最终做到了:
# Keep as data.tables
sas7bdat <- setDT(read.sas7bdat("psu97ai.sas7bdat"))
haven <- setDT(read_sas("psu97ai.sas7bdat"))
# read.sas7bdat prefers strings as factors,
# and as of now has no stringsAsFactors argument
# with which to prevent this
idj_factor <- sapply(haven, is.factor)
# Reset all factor columns as characters
sas7bdat[ , (idj_factor) := lapply(.SD, as.character), .SDcols = idj_factor]
# Check equality of the tables
all.equal(sas7bdat, haven, check.attributes = FALSE)
# [1] TRUE
但是,请注意 read.sas7bdat
为文件保留了大量属性列表,可能是 SAS 的保留:
str(sas7bdat)
# ...
# - attr(*, "column.info")=List of 70
# ..$ :List of 12
# .. ..$ name : chr "NCESSCH"
# .. ..$ offset: int 200
# .. ..$ length: int 12
# .. ..$ type : chr "character"
# .. ..$ format: chr "$"
# .. ..$ fhdr : int 0
# .. ..$ foff : int 76
# .. ..$ flen : int 1
# .. ..$ label : chr "UNIQUE SCHOOL ID (NCES ASSIGNED)"
# .. ..$ lhdr : int 0
# .. ..$ loff : int 44
# .. ..$ llen : int 32
# ...
所以,如果您 需要 这些属性(例如,我知道有些人特别热衷于 label
),也许 read.sas7bdat
毕竟是你的选择。
自 2018 年 1 月 18 日起,haven R 库会将 sas 和 stata 数据集加载到 R 环境中。在 R 中,只需:
library(haven)
data <- read_sas("C:/temp/mysasdataset.sas7bdat")
View(data)
您也可以在 R studio 中手动加载数据。在环境窗格中,选择
Import Dataset > From SAS...
Select 文件位置并单击 "Import"
另一个选择可能是我的 readsas
包裹。语法类似于 foreign
包中的一个和 read-series 的其他语法。导入的数据作为带有属性的 data.frame()
返回。该软件包是从头开始编写的,具有读取未压缩和压缩 sas7bdat
文件的支持。
尽管已经过大量测试,该软件包仍处于早期开发阶段。
library(readsas)
dat <- read.sas("psu97ai.sas7bdat")
R 有哪些选项可以将原生 SAS 格式的文件 sas7bdat
读取到 R 中?
1997-98 年来自 LEA Universe 的 NCES Common Core, for example, contains an extensive repository of data files saved in this format. For concreteness, let's focus on trying to read in this 文件,其中包含从 A 到 I 的所有州的实体的教育机构级别人口统计数据。
这是来自 SAS 的数据预览:
将这些数据引入我的 R 环境的最简单方法是什么?我没有任何可用的 SAS 版本,也不愿意付费,所以简单地将其转换为 .csv 会很麻烦。
问题
问题似乎是您尝试使用的文件格式不正确。具体来说,空白单元格未编码(R
使用 NA
),而只是留空。当尝试加载制表符分隔的文件时,这会给 R 带来问题,它认为列数不正确。
使用 SAS 文件的解决方法
我找到了一个解决方法,使用 sas7bdat
包加载 SAS 文件,然后将空白单元格 (""
) 重新编码为 NA:
install.packages("sas7bdat")
require("sas7bdat")
download.file("http://nces.ed.gov/ccd/Data/zip/ag121a_supp_sas.zip",
destfile = "sas.zip")
unzip("sas.zip")
sas <- read.sas7bdat(file = "ag121a_supp.sas7bdat", debug = FALSE)
sas[sas == ""] <- NA
不过,此方法有两个问题需要注意:
- 速度很慢(查看评论)
sas7bdat
包在其作者撰写本文时目前被认为是实验性的。因此它可能不会加载所有 sas 文件,我会在使用前彻底检查它所做的不一致。
非 R 解决方案
它不完全规范,但您也可以下载制表符分隔的文件,在 LibreOffice Calc 中打开它们(Microsoft Excel 似乎搞砸了),然后通过搜索 ""
并替换为 NA
.
sas7bdat
除了我正在查看的一个文件(具体来说,this one)以外的所有文件都工作正常;在向 sas7bdat
开发人员 Matthew Shotwell 报告错误时,他还向我指出了 Hadley 在 R 中的 haven
包的方向,它也有一个 read_sas
方法。
这种方法的优越性有两个原因:
1) 读取上面链接的文件没有任何问题
2) 它比 read.sas7bdat
快 much(我说的是 much)。这是一个快速基准(在 this 文件上,比其他文件小)作为证据:
microbenchmark(times=10L,
read.sas7bdat("psu97ai.sas7bdat"),
read_sas("psu97ai.sas7bdat"))
Unit: milliseconds
expr min lq mean median uq max neval cld
read.sas7bdat("psu97ai.sas7bdat") 66696.2955 67587.7061 71939.7025 68331.9600 77225.1979 82836.8152 10 b
read_sas("psu97ai.sas7bdat") 397.9955 402.2627 410.4015 408.5038 418.1059 425.2762 10 a
没错——haven::read_sas
比 sas7bdat::read.sas7bdat
少 99.5% 的时间。
次要更新
我以前无法弄清楚这两种方法是否产生了相同的数据(即,两者在读取数据方面具有相同的保真度),但最终做到了:
# Keep as data.tables
sas7bdat <- setDT(read.sas7bdat("psu97ai.sas7bdat"))
haven <- setDT(read_sas("psu97ai.sas7bdat"))
# read.sas7bdat prefers strings as factors,
# and as of now has no stringsAsFactors argument
# with which to prevent this
idj_factor <- sapply(haven, is.factor)
# Reset all factor columns as characters
sas7bdat[ , (idj_factor) := lapply(.SD, as.character), .SDcols = idj_factor]
# Check equality of the tables
all.equal(sas7bdat, haven, check.attributes = FALSE)
# [1] TRUE
但是,请注意 read.sas7bdat
为文件保留了大量属性列表,可能是 SAS 的保留:
str(sas7bdat)
# ...
# - attr(*, "column.info")=List of 70
# ..$ :List of 12
# .. ..$ name : chr "NCESSCH"
# .. ..$ offset: int 200
# .. ..$ length: int 12
# .. ..$ type : chr "character"
# .. ..$ format: chr "$"
# .. ..$ fhdr : int 0
# .. ..$ foff : int 76
# .. ..$ flen : int 1
# .. ..$ label : chr "UNIQUE SCHOOL ID (NCES ASSIGNED)"
# .. ..$ lhdr : int 0
# .. ..$ loff : int 44
# .. ..$ llen : int 32
# ...
所以,如果您 需要 这些属性(例如,我知道有些人特别热衷于 label
),也许 read.sas7bdat
毕竟是你的选择。
自 2018 年 1 月 18 日起,haven R 库会将 sas 和 stata 数据集加载到 R 环境中。在 R 中,只需:
library(haven)
data <- read_sas("C:/temp/mysasdataset.sas7bdat")
View(data)
您也可以在 R studio 中手动加载数据。在环境窗格中,选择
Import Dataset > From SAS...
Select 文件位置并单击 "Import"
另一个选择可能是我的 readsas
包裹。语法类似于 foreign
包中的一个和 read-series 的其他语法。导入的数据作为带有属性的 data.frame()
返回。该软件包是从头开始编写的,具有读取未压缩和压缩 sas7bdat
文件的支持。
尽管已经过大量测试,该软件包仍处于早期开发阶段。
library(readsas)
dat <- read.sas("psu97ai.sas7bdat")