SAS 无法打开使用“haven”从 R 导出的文件
Exported file from R using `haven` cannot be opened by SAS
当使用 haven::write_sas()
从 R 导出数据时,SAS EG/9.4 无法识别(即无法加载)生成的 sas7bdat 文件。尽管有其他几个软件包(例如 foreign
提供替代方法,我希望找到一种相对自动化的方法将数据集从我的 R 会话直接推送到 SAS。
当使用 haven
时,文件已生成但无法通过 SAS EG 或 9.4 打开:
# Load package
library(haven)
# Save data
write_sas(mtcars, "mtcars.sas7bdat")
使用foreign
替代haven
:
library(foreign)
write.foreign(df = mtcars,
datafile = 'mtcars.txt',
codefile = 'mtcars.sas',
dataname = 'libraryname.tablename', # Destination in SAS to save the data
package = 'SAS')
运行 foreign
的 SAS 代码输出成功。
* Written by R;
* write.foreign(df = mtcars, datafile = "mtcars.txt", codefile = "mtcars.sas", ;
DATA libraryname.tablename ;
INFILE "mtcars.txt"
DSD
LRECL= 43 ;
INPUT
mpg
cyl
disp
hp
drat
wt
qsec
vs
am
gear
carb
;
RUN;
但是,这些方法都不能帮助自动将数据从 R 直接推送到 SAS 库,后者更可取。
关于 GitHub describing some of the challenges when exporting data from R for use in SAS via haven
. In addition to providing a solution on how to automate data transfer from R to SAS, I hope this can serve as an answer to some related questions 的讨论很长。
如果想使用 SAS 设计的工具来实现与 R 的互操作性,GitHub 上的 RSWAT
可能是更可靠的选择。但是,这将假定您有权访问为此目的配置的 SAS Cloud Analytics Services。
如果您在计算机上使用 SAS 9.4,并且可能还连接到 SAS 服务器(即使用 rsubmit;
命令),那么将数据集直接从 R 传递到SAS 库。分为三个步骤:
- 为 SAS 格式化数据集;虽然
foreign
会做很多格式更改,但我更喜欢将因子转换回字符并将 NA
替换为 ""
。我发现这确保同事无需特殊格式即可在 SAS 中打开最终 table。
# Example data
data <- data.frame(ID = c(123, NA, 125),
disease = factor(c('syphilis', 'gonorrhea', NA)),
AdmitDate = as.Date(c("2014-04-05", NA, "2016-02-03")),
DOB = as.Date(c("1990-01-01", NA, NA)))
# Function defined for converting factors and blanks
convert_format_r2sas <- function(data){
data <- data %>%
dplyr::mutate_if(is.factor, as.character) %>%
dplyr::mutate_if(is.character, tidyr::replace_na, replace = "")
return(data)
}
# Convert some formatting
data <- convert_format_r2sas(data)
- 使用
foreign
导出数据和相关代码
library(foreign)
# Ensure the data and code files are saved in an easily accessible location (ideally in or downstream of your R project directory)
write.foreign(df = data ,
datafile = 'data.txt',
codefile = 'data.sas',
dataname = 'libraryname.tablename', # Destination in SAS to save the data
package = 'SAS')
- 使用自定义函数将代码传递到本地 SAS 安装。您可能需要调整 SAS.exe 的位置以及配置文件。这既可以传递 SAS 文件列表,也可以传递直接用 R 编写的 SAS 代码作为字符向量。
# Define function for passing the code to SAS and upload data (may require tweaking the local SAS installation location and configuration file)
pass_code_to_sas <- function(sas_file_list = NULL, inputstring = NULL,
sas_path = "C:/LocationTo/SASHome/SASFoundation/9.4/sas.exe",
configFile = "C:/LocationTo/SASHome/SASFoundation/9.4/SASV9.CFG") {
# If provided list of scripts, check they are all valid
if(!is.null(sas_file_list)){
if(any(purrr::map_lgl(sas_file_list, file.exists)) == FALSE | is.list(sas_file_list) == F){
stop("You entered an invalid file location or did not provide the locations as a list of characters")
}
}
sink(file.path(R.home(), "temp_codePass.sas"))
if(!is.null(sas_file_list)){
for(i in 1:length(sas_file_list)){
cat(readLines(sas_file_list[[i]]), sep = "\n")
}
}
cat(inputstring)
sink()
# Output message to view what code was sent...
message(paste0("The above info was passed to SAS: ",
if(!is.null(sas_file_list)){for(i in 1:length(sas_file_list)){cat(readLines(sas_file_list[[i]]), sep = "\n")}},
print(inputstring)))
# Run SAS
system2(sas_path,
args = paste0(
"\"", file.path(R.home(), "temp_codePass.sas"), "\"",
if(!is.null(configFile)) { paste0(" -config \"", configFile, "\"")}
)
)
# Delete the SAS file
file.remove(file.path(R.home(), "temp_codePass.sas"))
}
# Pass data to SAS
pass_code_to_sas(sas_file_list = 'path2codefile/data.sas')
当使用 haven::write_sas()
从 R 导出数据时,SAS EG/9.4 无法识别(即无法加载)生成的 sas7bdat 文件。尽管有其他几个软件包(例如 foreign
提供替代方法,我希望找到一种相对自动化的方法将数据集从我的 R 会话直接推送到 SAS。
当使用 haven
时,文件已生成但无法通过 SAS EG 或 9.4 打开:
# Load package
library(haven)
# Save data
write_sas(mtcars, "mtcars.sas7bdat")
使用foreign
替代haven
:
library(foreign)
write.foreign(df = mtcars,
datafile = 'mtcars.txt',
codefile = 'mtcars.sas',
dataname = 'libraryname.tablename', # Destination in SAS to save the data
package = 'SAS')
运行 foreign
的 SAS 代码输出成功。
* Written by R;
* write.foreign(df = mtcars, datafile = "mtcars.txt", codefile = "mtcars.sas", ;
DATA libraryname.tablename ;
INFILE "mtcars.txt"
DSD
LRECL= 43 ;
INPUT
mpg
cyl
disp
hp
drat
wt
qsec
vs
am
gear
carb
;
RUN;
但是,这些方法都不能帮助自动将数据从 R 直接推送到 SAS 库,后者更可取。
关于 GitHub describing some of the challenges when exporting data from R for use in SAS via haven
. In addition to providing a solution on how to automate data transfer from R to SAS, I hope this can serve as an answer to some related questions 的讨论很长。
如果想使用 SAS 设计的工具来实现与 R 的互操作性,GitHub 上的 RSWAT
可能是更可靠的选择。但是,这将假定您有权访问为此目的配置的 SAS Cloud Analytics Services。
如果您在计算机上使用 SAS 9.4,并且可能还连接到 SAS 服务器(即使用 rsubmit;
命令),那么将数据集直接从 R 传递到SAS 库。分为三个步骤:
- 为 SAS 格式化数据集;虽然
foreign
会做很多格式更改,但我更喜欢将因子转换回字符并将NA
替换为""
。我发现这确保同事无需特殊格式即可在 SAS 中打开最终 table。
# Example data
data <- data.frame(ID = c(123, NA, 125),
disease = factor(c('syphilis', 'gonorrhea', NA)),
AdmitDate = as.Date(c("2014-04-05", NA, "2016-02-03")),
DOB = as.Date(c("1990-01-01", NA, NA)))
# Function defined for converting factors and blanks
convert_format_r2sas <- function(data){
data <- data %>%
dplyr::mutate_if(is.factor, as.character) %>%
dplyr::mutate_if(is.character, tidyr::replace_na, replace = "")
return(data)
}
# Convert some formatting
data <- convert_format_r2sas(data)
- 使用
foreign
导出数据和相关代码
library(foreign)
# Ensure the data and code files are saved in an easily accessible location (ideally in or downstream of your R project directory)
write.foreign(df = data ,
datafile = 'data.txt',
codefile = 'data.sas',
dataname = 'libraryname.tablename', # Destination in SAS to save the data
package = 'SAS')
- 使用自定义函数将代码传递到本地 SAS 安装。您可能需要调整 SAS.exe 的位置以及配置文件。这既可以传递 SAS 文件列表,也可以传递直接用 R 编写的 SAS 代码作为字符向量。
# Define function for passing the code to SAS and upload data (may require tweaking the local SAS installation location and configuration file)
pass_code_to_sas <- function(sas_file_list = NULL, inputstring = NULL,
sas_path = "C:/LocationTo/SASHome/SASFoundation/9.4/sas.exe",
configFile = "C:/LocationTo/SASHome/SASFoundation/9.4/SASV9.CFG") {
# If provided list of scripts, check they are all valid
if(!is.null(sas_file_list)){
if(any(purrr::map_lgl(sas_file_list, file.exists)) == FALSE | is.list(sas_file_list) == F){
stop("You entered an invalid file location or did not provide the locations as a list of characters")
}
}
sink(file.path(R.home(), "temp_codePass.sas"))
if(!is.null(sas_file_list)){
for(i in 1:length(sas_file_list)){
cat(readLines(sas_file_list[[i]]), sep = "\n")
}
}
cat(inputstring)
sink()
# Output message to view what code was sent...
message(paste0("The above info was passed to SAS: ",
if(!is.null(sas_file_list)){for(i in 1:length(sas_file_list)){cat(readLines(sas_file_list[[i]]), sep = "\n")}},
print(inputstring)))
# Run SAS
system2(sas_path,
args = paste0(
"\"", file.path(R.home(), "temp_codePass.sas"), "\"",
if(!is.null(configFile)) { paste0(" -config \"", configFile, "\"")}
)
)
# Delete the SAS file
file.remove(file.path(R.home(), "temp_codePass.sas"))
}
# Pass data to SAS
pass_code_to_sas(sas_file_list = 'path2codefile/data.sas')