检查使用整洁评估的函数中列的 class
Checking the class of a column in a function that uses tidy evaluation
我没有将列名作为字符串引用,但是当我没有将列名作为字符串引用时,如何检查 if 语句中的 class:
我的问题是 if statement
波纹管:我试过 rlang::as_name
、quote
等
df <- tibble::tibble( time_text = as.character(as.POSIXct("2018-02-03 08:00:00", tz = "UTC") + rnorm(100, 0, 60*60*60)))
date_from_text <- function(df, x){
if(!class(df[[deparse(x)]]) %in% c("POSIXct", "POSIXt" )) {
x <- rlang::enquo(x)
name <- rlang::quo_name(x)
out <- df %>%
dplyr::mutate(!!name := lubridate::ymd_hms(!!x))
}
else {
stop("Seems that column is in the right format already")
}
}
date_from_text(df, time_text)
Error in deparse(x) : object 'time_text' not found
当您在 if
语句之前使用 x <- rlang::enquo(x)
和 name <- rlang::quo_name(x)
时有效:
date_from_text <- function(df, x){
x <- rlang::enquo(x)
name <- rlang::quo_name(x)
if(!inherits(df[[name]], c("POSIXct", "POSIXt"))) {
out <- dplyr::mutate(df, !!name := lubridate::ymd_hms(!!x))
} else {
stop("Seems that column is in the right format already")
}
}
我将 if
语句中的要求更改为 !inherits(df[[name]], c("POSIXct", "POSIXt"))
。
在您的原始代码中,只会检查 class 向量的第一个元素,而 inherits 检查是否继承了任何指定的 classes 。
my.df <- tibble::tibble(time_text = as.character(as.POSIXct("2018-02-03 08:00:00", tz = "UTC") + rnorm(100, 0, 60*60*60)))
my.df2 <- date_from_text(my.df, time_text)
my.df2
# A tibble: 100 x 1
# time_text
# <dttm>
# 1 2018-02-06 18:38:46
# 2 2018-01-31 16:16:15
# 3 2018-02-04 05:52:32
# 4 2018-02-05 23:31:50
# 5 2018-02-06 13:00:34
# 6 2018-02-01 16:16:24
# 7 2018-02-05 15:09:45
# 8 2018-02-04 04:23:00
# 9 2018-02-03 06:55:18
# 10 2018-01-29 01:06:26
# ... with 90 more rows
date_from_text(my.df2, time_text)
Error in date_from_text(my.df2, time_text) :
Seems that column is in the right format already
感谢@KonradRudolph 用他的评论改进了这个答案。
或引用您要检查的column-name
date_from_text <- function(df, x){
if( !class( df[[x]] ) %in% c( "POSIXct", "POSIXt" )) {
df[[x]] <- lubridate::ymd_hms( df[[x]] )
return( df[[x]] )
}
else {
stop( "Seems that column is in the right format already" )
}
}
date_from_text( df, "time_text" )
我们还可以使用来自 rlang
的新 curly-curly ({{}}
) 运算符
library(rlang)
date_from_text <- function(df, x){
if (!class(df %>% pull({{x}})) %in% c("POSIXct", "POSIXt")) {
x <- rlang::enquo(x)
name <- rlang::quo_name(x)
df %>% mutate(!!name := lubridate::ymd_hms({{x}}))
} else {
stop("Seems that column is in the right format already")
}
}
df1 <- date_from_text(df, time_text)
df1
# A tibble: 100 x 1
# time_text
# <dttm>
# 1 2018-02-05 06:47:00.947
# 2 2018-02-06 13:25:36.656
# 3 2018-01-31 18:45:57.358
# 4 2018-02-05 02:16:56.179
# 5 2018-02-06 15:43:30.417
# 6 2018-02-07 14:59:56.203
# 7 2018-02-01 04:25:29.382
# 8 2018-01-31 19:11:13.136
# 9 2018-02-02 18:47:06.812
#10 2018-02-03 17:31:45.790
# … with 90 more rows
date_from_text(df1, time_text)
Error in date_from_text(df1, time_text) :
Seems that column is in the right format already
我没有将列名作为字符串引用,但是当我没有将列名作为字符串引用时,如何检查 if 语句中的 class:
我的问题是 if statement
波纹管:我试过 rlang::as_name
、quote
等
df <- tibble::tibble( time_text = as.character(as.POSIXct("2018-02-03 08:00:00", tz = "UTC") + rnorm(100, 0, 60*60*60)))
date_from_text <- function(df, x){
if(!class(df[[deparse(x)]]) %in% c("POSIXct", "POSIXt" )) {
x <- rlang::enquo(x)
name <- rlang::quo_name(x)
out <- df %>%
dplyr::mutate(!!name := lubridate::ymd_hms(!!x))
}
else {
stop("Seems that column is in the right format already")
}
}
date_from_text(df, time_text)
Error in deparse(x) : object 'time_text' not found
当您在 if
语句之前使用 x <- rlang::enquo(x)
和 name <- rlang::quo_name(x)
时有效:
date_from_text <- function(df, x){
x <- rlang::enquo(x)
name <- rlang::quo_name(x)
if(!inherits(df[[name]], c("POSIXct", "POSIXt"))) {
out <- dplyr::mutate(df, !!name := lubridate::ymd_hms(!!x))
} else {
stop("Seems that column is in the right format already")
}
}
我将 if
语句中的要求更改为 !inherits(df[[name]], c("POSIXct", "POSIXt"))
。
在您的原始代码中,只会检查 class 向量的第一个元素,而 inherits 检查是否继承了任何指定的 classes 。
my.df <- tibble::tibble(time_text = as.character(as.POSIXct("2018-02-03 08:00:00", tz = "UTC") + rnorm(100, 0, 60*60*60)))
my.df2 <- date_from_text(my.df, time_text)
my.df2
# A tibble: 100 x 1
# time_text
# <dttm>
# 1 2018-02-06 18:38:46
# 2 2018-01-31 16:16:15
# 3 2018-02-04 05:52:32
# 4 2018-02-05 23:31:50
# 5 2018-02-06 13:00:34
# 6 2018-02-01 16:16:24
# 7 2018-02-05 15:09:45
# 8 2018-02-04 04:23:00
# 9 2018-02-03 06:55:18
# 10 2018-01-29 01:06:26
# ... with 90 more rows
date_from_text(my.df2, time_text)
Error in date_from_text(my.df2, time_text) : Seems that column is in the right format already
感谢@KonradRudolph 用他的评论改进了这个答案。
或引用您要检查的column-name
date_from_text <- function(df, x){
if( !class( df[[x]] ) %in% c( "POSIXct", "POSIXt" )) {
df[[x]] <- lubridate::ymd_hms( df[[x]] )
return( df[[x]] )
}
else {
stop( "Seems that column is in the right format already" )
}
}
date_from_text( df, "time_text" )
我们还可以使用来自 rlang
{{}}
) 运算符
library(rlang)
date_from_text <- function(df, x){
if (!class(df %>% pull({{x}})) %in% c("POSIXct", "POSIXt")) {
x <- rlang::enquo(x)
name <- rlang::quo_name(x)
df %>% mutate(!!name := lubridate::ymd_hms({{x}}))
} else {
stop("Seems that column is in the right format already")
}
}
df1 <- date_from_text(df, time_text)
df1
# A tibble: 100 x 1
# time_text
# <dttm>
# 1 2018-02-05 06:47:00.947
# 2 2018-02-06 13:25:36.656
# 3 2018-01-31 18:45:57.358
# 4 2018-02-05 02:16:56.179
# 5 2018-02-06 15:43:30.417
# 6 2018-02-07 14:59:56.203
# 7 2018-02-01 04:25:29.382
# 8 2018-01-31 19:11:13.136
# 9 2018-02-02 18:47:06.812
#10 2018-02-03 17:31:45.790
# … with 90 more rows
date_from_text(df1, time_text)
Error in date_from_text(df1, time_text) : Seems that column is in the right format already