R 中函数内的引号、准引号和正则表达式出现问题

Trouble with quotes and quasi-quotation and regular expressions inside a function in R

我正在尝试编写一个使用 gsub 查找和替换某些字符串的函数。我有 10 多个 excel 电子表格,其中包含使用标准瑞典分隔符表示千位和小数的货币值列表,即小数点用逗号而不是句点表示,千位分隔符是 space 和不是逗号。英语中的 1,000.31 变成瑞典语中的 1 000,31 是什么意思?我正在尝试编写一个函数来消除千位分隔符所在的 space,并找到逗号并将其替换为句点。

正常的 gsub 函数工作正常:

    df$Saldo <- gsub(",", ".", df$Saldo)
    df$Saldo <- gsub(" ", "", df$Saldo)

但是,我需要在 10 多个数据帧上执行此操作,所以我认为编写一个可以应用于每个数据帧的函数会更有效(我尝试编写的函数加上一个可重现的示例是下面提供)。这是我 运行 遇到问题的地方。我还应该提到我正在寻找 dplyr 解决方案。我在函数(下面)中得到的错误是错误:Quosures can only be unquoted within a quasiquotation context.

我承认,尽管我反复阅读了有关非标准评估和准报价的内容,但我仍然难以理解这些概念。我读过使用 dplyr 编程

https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html

我也看过:

https://rlang.r-lib.org/reference/quasiquotation.html

最后研究了几个类似problems/solutions的关于stack overflow的解决方法,但是好像对我没有用。大多数问题都是关于让正则表达式起作用,而不是让正则表达式在函数内部起作用。

这里是函数,比如它是:

     library(dplyr)
     replace_commas <- function(df1, c_name) {
      c_name <- enquo(c_name)
      df1 <- df1 %>% gsub(",", ".",!! c_name)
      return(df1)
      }

这是一个可重现的例子:

    df <- data.frame(Date = c("2018-12-15", "2018-11-04", "2018-10-26"), Saldo = c("123 432,45", "87 546,23", "9 564,82"))

    df_new <- replace_commas(df, Saldo)

我最想实现的是一个查找逗号并将其替换为句点的功能。但是,我也很感激关于如何在函数中包含正则表达式以删除不需要的 spaces.

的指针

您的代码的以下版本可以删除逗号并将其替换为小数,还可以删除空格,但您可能希望使用 R 的内置工具来代替,如下所示。

library(dplyr)

as.swedish <- function(from) as.numeric(gsub(" ", "", sub(",", ".", from)))
replace_commas <- function(df1, c_name) {
  c_name <- enquo(c_name)
  df1 %>% mutate_at(vars(!!c_name), as.swedish)
}   
df %>% replace_commas(Saldo)

以下假设有空格作为千​​位分隔符和逗号作为小数点除了1a只假设逗号作为小数点。

1) read.csv2 我们可以定义一个swedishclass然后在read.csv2中使用。这使用上面定义的 one-line 函数 as.swedish

# test data
Lines <- "Letter;Number\nA;1 200,3\nB;32\nC;2511,01"

# define swedish class
setClass("swedish")
setAs("character", "swedish", as.swedish)
setAs("factor", "swedish", as.swedish)

read.csv2(text = Lines, colClasses = list(Number = "swedish"))

给予:

  Letter  Number
1      A 1200.30
2      B   32.00
3      C 2511.01

1a) 如果我们没有空格作为千​​位分隔符,只有逗号作为小数点,那么我们可以使用 read.csv2:

Lines2 <- "Letter;Number\nA;1200,3\nB;32\nC;2511,01"
read.csv2(text = Lines2)

给予:

  Letter  Number
1      A 1200.30
2      B   32.00
3      C 2511.01

2) 转换 df 或使用 swedish class 从上面转换 Saldo in df:

transform(df, Saldo = as(Saldo, "swedish"))

给予:

        Date     Saldo
1 2018-12-15 123432.45
2 2018-11-04  87546.23
3 2018-10-26   9564.82

2a) 这也有效并且只使用上面的 as.swedish 函数而不是 swedish class.

transform(df, Saldo = as.swedish(Saldo))

或与dplyr几乎相同df %>% mutate(Saldo = as.swedish(Saldo))

3) 转换 df 的函数或定义此函数,其中 names 是要从瑞典语转换的列名称的字符向量。如果我们将名称作为字符串传递,则既不需要 quasi-quotation 也不需要相应的内置 R 工具,这看起来是一个更好的设计。这使用上面的 as.swedish 函数而不是 swedish class.

swedish <- function(data, names) replace(data, names, lapply(data[names], as.swedish))
swedish(df, "Saldo")

library(dplyr)
df %>% swedish("Saldo")