用于导入数据集和管道的 R 函数根据字段 name/existence 创建变量

R Function to import data set and pipeline create variables based on field name/existence

我正在创建一个函数来自动导入多个数据集,但在管道中分配变量值时遇到困难。

任务:

我有 20 多个数据集需要导入并计算和创建相同的变量。输入数据集包含相同的字段,除了一个字段,其名称可以是三个可能值之一('varYEAR',其中 'YEAR' 是三个可能的年份之一),但其基础数据是同一类型。我试图将此 varYEAR 向量的值分配给一个统一命名的变量 'varXXXX' ,以便进一步的突变可以引用后一个变量而不必担心原始变量名称。下面的代码已经过简化,以关注问题的症结所在。

当前示例 Code/Output:

set_import <- function(input_path,year) {
   temp_set <- read_table(input_path) %>%
     mutate(MSAXXXX = ifelse(exists('var2003'),var2003,var2013))
}

View(temp_set)

       var2003        varXXXX
 1     41929          41929
 2     33820          41929
 3     27642          41929
 4     88111          41929

为此我尝试了几种不同的方法,包括: mutate(varXXXX = ifelse('var2003' %in% names(.),var2003,var2013)) 以及使用 temp_set$MSAXXXX = as.character(ifelse('var2003' %in% names(temp_set),temp_set$var2003,var2013)) 在管道外进行尝试。每个都产生了上面相同的输出集。

期望输出:

View(temp_set)

       var2003        varXXXX
 1     41929          41929
 2     33820          33820          
 3     27642          27642          
 4     88111          88111          

我现在可以推测的最好结果是 'if' 语句基于单个检查,并且出于某种原因,它使用在所述检查中找到的第一个值填充 varXXXX 字段。我不知所措,非常感谢您的帮助!提前致谢。

解决方案

只需使用regex更改列名:

temp_set <- read_table(input_path)

names(temp_set) <- gsub(x = names(temp_set), pattern = "^(.+)(\d{4,4})$", replacement = "\1XXXX")

或等效于 `names<-`() in the dplyr 工作流程:

temp_set <- read_table(input_path) %>%
  `names<-`(gsub(x = names(.), pattern = "^(.+)(\d{4,4})$", replacement = "\1XXXX"))

正则表达式

pattern = "^(.+)(\d{4,4})$" 将每个名字分成两个 capturing groups:

  1. 任何正长度的前缀:.+
  2. 某个年份由 4 位数字组成:\d{4,4}

然后 replacement = "\1XXXX" 将第一组 (\1) 添加到代码 (XXXX) 之前;所以代码基本上“取代”了年份。

例子

这里有两种可能的情况,其中 MSAXXXX 列分别以 MSA2003MSA2013 开始:

case_1 <- data.frame(
  MSA2003 = c(41929, 33820, 27642, 88111),
  var2019 = c(41929, 33820, 27642, 88111),
  other_var = 1:4
)
case_1
#>   MSA2003 var2019 other_var
#> 1   41929   41929         1
#> 2   33820   33820         2
#> 3   27642   27642         3
#> 4   88111   88111         4

case_2 <- data.frame(
  MSA2013 = c(41929, 33820, 27642, 88111),
  var2009 = c(41929, 33820, 27642, 88111),
  other_var = 1:4
)
case_2
#>   MSA2013 var2009 other_var
#> 1   41929   41929         1
#> 2   33820   33820         2
#> 3   27642   27642         3
#> 4   88111   88111         4

请注意解决方案如何标准化名称中包含年份的所有变量,同时保持其他变量不变:

library(dplyr)

case_1 %>%
  `names<-`(gsub(x = names(.), pattern = "^(.+)(\d{4,4})$", replacement = "\1XXXX"))
#>   MSAXXXX varXXXX other_var
#> 1   41929   41929         1
#> 2   33820   33820         2
#> 3   27642   27642         3
#> 4   88111   88111         4


case_2 %>%
  `names<-`(gsub(x = names(.), pattern = "^(.+)(\d{4,4})$", replacement = "\1XXXX"))
#>   MSAXXXX varXXXX other_var
#> 1   41929   41929         1
#> 2   33820   33820         2
#> 3   27642   27642         3
#> 4   88111   88111         4