在 dplyr 链中调用 mutate 的 gsub 内部函数给出错误

gsub inside function with mutate called in dplyr chain gives error

我有以下示例数据(真实数据包含具有数字和字符变量的其他列):

structure(list(AM = structure(1:20, .Label = c("AMP_R", "AZI_R", 
"CHL_R", "CIP_R", "COL_R", "ERY_R", "ETP_R", "F.C_R", "FEP_R", 
"FOT_R", "FOX_R", "GEN_R", "IMI_R", "MERO_R", "NAL_R", "STR_R", 
"SULFA_R", "T.C_R", "TAZ_R", "TET_R"), class = "factor")), .Names = "AM", row.names = c(NA, 
-20L), class = "data.frame")

我试图创建一个函数来检测数据框中的列是否包含以“_R”结尾的变量。如果他们这样做,它将删除这个结尾并根据转换 table 继续将变量重命名为全名。如果“_R”结尾不存在,它将直接转换名称。

我在函数的第一部分尝试了以下操作:

library(dplyr)

convert_AM_names <- function(data, col) {
    data %>%
      mutate(col = gsub("(.*?)_R", "\1", col))
}

我想在 dplyr 链中使用它,像这样:

AM <- AM %>%
  rowwise() %>%
  convert_AM_names(., AM)

但是,当我这样做时,出现错误 "Error in mutate_impl(.data, dots): Column "col" must be length 1, not 20"

我看到类似的问题已在 SO 此处得到解决,但对于大多数问题,解决方案是使用 rowwise(),这在此处似乎不起作用。有什么建议吗?

您可以使用 mutate_at(),它允许您 select 列并对其应用函数。

AM %>% 
  mutate_at(.vars = "AM", 
            .funs = gsub,
            pattern = "(.*?)_R",
            replacement = "\1")

如果你愿意,你也可以重写你的函数:

convert_AM_names <- function(col) {
  gsub("(.*?)_R", "\1", col)
}

并在mutate_at()中使用:

AM %>% 
  mutate_at(.vars = "AM", 
            .funs = convert_AM_names)

在这两种情况下,结果如下所示:

      AM
1    AMP
2    AZI
3    CHL
4    CIP
5    COL
6    ERY
7    ETP
8    F.C
9    FEP
10   FOT
11   FOX
12   GEN
13   IMI
14  MERO
15   NAL
16   STR
17 SULFA
18   T.C
19   TAZ
20   TET

您可以为正则表达式使用 锚点,它仅在 _R 正好位于末尾时才匹配:

convert_AM_names <- function(col) {
  gsub("(.*)_R$", "\1", col)
}

library(dplyr)
df %>%
  mutate(AM = convert_AM_names(AM))

或直接 - 没有 convert_AM_names() 的开销:

df %>%
  mutate(AM = gsub("(.*)_R$", "\1", AM))

两者都会产生:

      AM
1    AMP
2    AZI
3    CHL
4    CIP
5    COL
6    ERY
7    ETP
8    F.C
9    FEP
10   FOT
11   FOX
12   GEN
13   IMI
14  MERO
15   NAL
16   STR
17 SULFA
18   T.C
19   TAZ
20   TET