R - 函数式编程问题 -- map_df & Regex



我正在尝试使用函数式编程方法组合多个电子表格(大约20个(。每个电子表格都包含一年的数据。它们很混乱,列没有命名,或者同一列的名称在电子表格中发生变化。

我最初对每个电子表格单独进行了所有的清理,但我想学习如何使用函数编程来进行清理,使其更具可复制性。

我的方法是构建一个正则表达式来匹配指定列的所有不同名称,然后使用自定义函数/regex重命名该列。我想我可以使用map_dfr将此函数应用于所有不同的电子表格,以生成最终的数据帧。

然而,我遇到了两个问题:

  1. R中的正则表达式引擎似乎打开了全局参数,无法关闭它。我想按顺序匹配正则表达式中的不同可能性,并在它找到第一个匹配时停止,而不是所有匹配。例如,在我导入电子表格后,有时会有多个未定义的列,它们的名称为...1等。我只想匹配第一个实例。我似乎不知道是否可以禁用全局参数,或者用一种更聪明的方式编写正则表达式,使其在第一次匹配后停止。还有没有其他更好的方法来解决这个问题?

  2. 当我传递我的自定义函数时,它似乎在单个数据帧上运行得很好,我从map_df中得到了一个错误,我不太确定为什么。

我在下面制作了一个最低限度的reprex,我认为这突出了问题。

所有的想法都受到了极大的欢迎,包括其他方法,因为这肯定是人们遇到的一个非常常见的问题。谢谢

library(tidyverse)
year_1 <- tribble(
~`...1`, ~admissions,
"Hospital 1", 10,
"Hospital 2", 100,
"hospital 3", 200
)
year_2 <- tribble(
~provider_code, ~`...2`, ~admissions,
"H1", "Hospital 1", 20,
"H2", "Hospital 2", 400,
"H3", "hospital 3", 500
)
year_3 <- tribble(
~"Hospital provider code", ~"Commissioning region/Provider", ~admissions,
"H1", "Hospital 1", 350,
"H2", "Hospital 2", 350,
"H3", "hospital 3", 550
)

clean_up_area_column_name <- function(x){
rename({{x}}, area = matches("\.{3}[0-9]|commissioning region|hospital provider", ignore.case = TRUE))
}
clean_up_area_column_name(year_1)
#> # A tibble: 3 × 2
#>   area       admissions
#>   <chr>           <dbl>
#> 1 Hospital 1         10
#> 2 Hospital 2        100
#> 3 hospital 3        200
clean_up_area_column_name(year_2)
#> # A tibble: 3 × 3
#>   provider_code area       admissions
#>   <chr>         <chr>           <dbl>
#> 1 H1            Hospital 1         20
#> 2 H2            Hospital 2        400
#> 3 H3            hospital 3        500
clean_up_area_column_name(year_3)
#> # A tibble: 3 × 3
#>   area1 area2      admissions
#>   <chr> <chr>           <dbl>
#> 1 H1    Hospital 1        350
#> 2 H2    Hospital 2        350
#> 3 H3    hospital 3        550
test_df <- map_dfr(c(year_1, year_2, year_3), clean_up_area_column_name)
#> Error in UseMethod("rename"): no applicable method for 'rename' applied to an object of class "character"

创建于2022-08-08由reprex包(v2.0.1(

map传递多个数据帧需要list

test_df <- map_dfr(list(year_1, year_2, year_3), clean_up_area_column_name)
# A tibble: 9 x 5
area       admissions provider_code area1 area2     
<chr>           <dbl> <chr>         <chr> <chr>     
1 Hospital 1         10 NA            NA    NA        
2 Hospital 2        100 NA            NA    NA        
3 hospital 3        200 NA            NA    NA        
4 Hospital 1         20 H1            NA    NA        
5 Hospital 2        400 H2            NA    NA        
6 hospital 3        500 H3            NA    NA        
7 NA                350 NA            H1    Hospital 1
8 NA                350 NA            H2    Hospital 2
9 NA                550 NA            H3    hospital 3

如果您只想像您所说的那样获取第一个实例,那么下面对函数的调整应该会起作用。重命名任何";区域1";至";区域";,则取消选择剩余的";区域";带有尾随数字的列名(area2、area3等(。

clean_up_area_column_name <- function(x){
rename({{x}}, 
area = matches("\.{3}[0-9]|commissioning region|hospital provider")) %>% 
rename(., area = matches("area1")) %>% 
select(-any_of(matches("area\d")))
}

我不确定您期望year_3返回什么,因为您的正则表达式似乎与provider_codearea:匹配

map_dfr(list(year_1, year_2, year_3), clean_up_area_column_name)
# A tibble: 9 × 3
area       admissions provider_code
<chr>           <dbl> <chr>        
1 Hospital 1         10 NA           
2 Hospital 2        100 NA           
3 hospital 3        200 NA           
4 Hospital 1         20 H1           
5 Hospital 2        400 H2           
6 hospital 3        500 H3           
7 H1                350 NA           
8 H2                350 NA           
9 H3                550 NA  

最新更新