1

使用 导出 R 中haven::write_sas()的数据时,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')

运行 SAS 代码输出foreign是成功的。

* 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 library中,这将是可取的。

4

1 回答 1

3

GitHub 上有一个冗长的讨论,描述了从 R 导出数据以用于 SAS 时的一些挑战haven。除了提供有关如何自动将数据从 R 传输到 SAS 的解决方案之外,我希望这可以作为一些相关问题的答案。

如果想使用 SAS 设计的工具与 R 进行互操作,RSWATGitHub可能是一个更强大的选择。但是,这将假定您有权访问为此目的配置的 SAS Cloud Analytics Services。

如果您在机器上使用 SAS 9.4 并且可能还连接到 SAS 服务器(即使用rsubmit;命令),则将数据集直接从 R 传递到 SAS 库应该相对简单。分为三个步骤:

  1. 为 SAS 格式化数据集;虽然foreign会做很多格式更改,但我更喜欢将因子转换回字符并NA替换为"". 我发现这可确保同事无需特殊格式即可在 SAS 中打开最终表格。
# 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)
  1. 用于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')
  1. 使用自定义函数将代码传递给本地 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')

于 2019-11-13T21:11:35.270 回答