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 我们可以定义一个swedish
class然后在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")
我正在尝试编写一个使用 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 我们可以定义一个swedish
class然后在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")