R dplyr::mutate_ 和 lubridate::parse_date_time 标准评估未按预期协同工作
R dplyr::mutate_ and lubridate::parse_date_time Standard Evaluation not working together as expected
我以为这是dplyr的一个bug,但也可能是我自己对标准评估的误解。如果有人能提供帮助那就太好了
考虑:
library(dplyr)
library(lubridate)
df <- frame_data( ~ start_date,
"07/15/2015 15:39",
"07/15/2015 15:42")
df_NSE <- df %>%
mutate(response_date = parse_date_time(start_date, orders ="mdY hm"))
我原以为像下面这样的东西是标准评估的等价物:
var_name <- "start_date"
df_SE_expected_to_work <- df %>%
mutate_(response_date = ~parse_date_time(var_name, orders ="mdY hm"))
但这只会引发警告并且 response_date 列只有空白行:
Warning message:
All formats failed to parse. No formats found.
即使使用 interp,我也尝试了很多变体,只是为了确保这不是我对 NSE 的理解,比如这个:
df_SE_interp_expected_to_work <- df %>%
mutate_(response_date = interp(~parse_date_time(var_name, orders ="mdY hm"), var_name = var_name))
但我得到了相同的结果
我能够破解这两种情况的有效解决方案:
df_SE_working <- df %>%
mutate_(response_date = ~parse_date_time(df[[var_name]], orders ="mdY hm"))
df_SE_interp_working <- df %>%
mutate_(response_date = interp(~parse_date_time(df[[var_name]], orders ="mdY hm"), var_name = var_name))
sessionInfo()
R version 3.2.3 (2015-12-10)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 14.04.4 LTS
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] lazyeval_0.1.10.9000 lubridate_1.5.0 ednaetl_0.1 purrr_0.2.0 psqlfun_0.1
[6] dplyr_0.4.3.9000 tidyr_0.4.0 uuid_0.1-2 RPostgreSQL_0.4 DBI_0.3.1
loaded via a namespace (and not attached):
[1] Rcpp_0.12.3 assertthat_0.1 R6_2.1.2 magrittr_1.5 stringi_1.0-1
[6] tools_3.2.3 stringr_1.0.0 yaml_2.1.13 parallel_3.2.3 rsconnect_0.4.1.11
[11] knitr_1.12.3
也许我只是遗漏了一些明显的东西来让它与 mutate_ 一起工作?
你试过了吗
df2 <- df %>%
mutate_(response_date = ~parse_date_time(start_date, orders ="mdY hm"))
使用公式符号只是为了避免 R 尝试计算给定表达式。因此,您可以使用与 NSE 中完全相同的调用,但添加了波浪线。
为了说明如何以编程方式执行此操作:
x <- "start_date"
df2 <- df %>%
mutate_(response_date = formula(sprintf("~parse_date_time(%s, orders='mdY hm')", x)))
标准评估评估事物(或多或少)就像它们在基础 R 中一样,这意味着如果您想评估 var_name
作为列名,则不能使用未加引号的列名;相反,您必须指定要子集化的 data.frame。
这里还有另一个问题:当您子集化为列名时,tbl_df
不是向量 return,而是单个列 tbl_df
,[=16] =] 无法处理。
例如,
> df[,var_name]
Source: local data frame [2 x 1]
start_date
(chr)
1 07/15/2015 15:39
2 07/15/2015 15:42
> dfdf <- as.data.frame(df)
> dfdf[,var_name]
[1] "07/15/2015 15:39" "07/15/2015 15:42"
这可能是 dplyr
努力使 一切 成为 return 数据框的结果。于是
df %>% mutate_(response_date = ~parse_date_time(df[,var_name], orders ="mdY hm"))
会失败,但是
dfdf <- as.data.frame(df)
dfdf %>% mutate_(response_date = ~parse_date_time(dfdf[,var_name], orders ="mdY hm"))
会起作用。您可以通过使用 [[
子集使其在上面工作,return 是 tbl_df
和 data.frame
的向量;另一种选择是用 unlist
.
强制解决问题
据我所知,没有办法调用链中创建的列或分组列(除了嵌套分组);总的来说,SE 选项打开了一些编程的可能性,但以方便为代价(加上大量的混乱)。
我以为这是dplyr的一个bug,但也可能是我自己对标准评估的误解。如果有人能提供帮助那就太好了
考虑:
library(dplyr)
library(lubridate)
df <- frame_data( ~ start_date,
"07/15/2015 15:39",
"07/15/2015 15:42")
df_NSE <- df %>%
mutate(response_date = parse_date_time(start_date, orders ="mdY hm"))
我原以为像下面这样的东西是标准评估的等价物:
var_name <- "start_date"
df_SE_expected_to_work <- df %>%
mutate_(response_date = ~parse_date_time(var_name, orders ="mdY hm"))
但这只会引发警告并且 response_date 列只有空白行:
Warning message:
All formats failed to parse. No formats found.
即使使用 interp,我也尝试了很多变体,只是为了确保这不是我对 NSE 的理解,比如这个:
df_SE_interp_expected_to_work <- df %>%
mutate_(response_date = interp(~parse_date_time(var_name, orders ="mdY hm"), var_name = var_name))
但我得到了相同的结果
我能够破解这两种情况的有效解决方案:
df_SE_working <- df %>%
mutate_(response_date = ~parse_date_time(df[[var_name]], orders ="mdY hm"))
df_SE_interp_working <- df %>%
mutate_(response_date = interp(~parse_date_time(df[[var_name]], orders ="mdY hm"), var_name = var_name))
sessionInfo()
R version 3.2.3 (2015-12-10)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 14.04.4 LTS
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] lazyeval_0.1.10.9000 lubridate_1.5.0 ednaetl_0.1 purrr_0.2.0 psqlfun_0.1
[6] dplyr_0.4.3.9000 tidyr_0.4.0 uuid_0.1-2 RPostgreSQL_0.4 DBI_0.3.1
loaded via a namespace (and not attached):
[1] Rcpp_0.12.3 assertthat_0.1 R6_2.1.2 magrittr_1.5 stringi_1.0-1
[6] tools_3.2.3 stringr_1.0.0 yaml_2.1.13 parallel_3.2.3 rsconnect_0.4.1.11
[11] knitr_1.12.3
也许我只是遗漏了一些明显的东西来让它与 mutate_ 一起工作?
你试过了吗
df2 <- df %>%
mutate_(response_date = ~parse_date_time(start_date, orders ="mdY hm"))
使用公式符号只是为了避免 R 尝试计算给定表达式。因此,您可以使用与 NSE 中完全相同的调用,但添加了波浪线。
为了说明如何以编程方式执行此操作:
x <- "start_date"
df2 <- df %>%
mutate_(response_date = formula(sprintf("~parse_date_time(%s, orders='mdY hm')", x)))
标准评估评估事物(或多或少)就像它们在基础 R 中一样,这意味着如果您想评估 var_name
作为列名,则不能使用未加引号的列名;相反,您必须指定要子集化的 data.frame。
这里还有另一个问题:当您子集化为列名时,tbl_df
不是向量 return,而是单个列 tbl_df
,[=16] =] 无法处理。
例如,
> df[,var_name]
Source: local data frame [2 x 1]
start_date
(chr)
1 07/15/2015 15:39
2 07/15/2015 15:42
> dfdf <- as.data.frame(df)
> dfdf[,var_name]
[1] "07/15/2015 15:39" "07/15/2015 15:42"
这可能是 dplyr
努力使 一切 成为 return 数据框的结果。于是
df %>% mutate_(response_date = ~parse_date_time(df[,var_name], orders ="mdY hm"))
会失败,但是
dfdf <- as.data.frame(df)
dfdf %>% mutate_(response_date = ~parse_date_time(dfdf[,var_name], orders ="mdY hm"))
会起作用。您可以通过使用 [[
子集使其在上面工作,return 是 tbl_df
和 data.frame
的向量;另一种选择是用 unlist
.
据我所知,没有办法调用链中创建的列或分组列(除了嵌套分组);总的来说,SE 选项打开了一些编程的可能性,但以方便为代价(加上大量的混乱)。