使用mutate()和ifelse()编写一个对数值向量进行分类的函数

时间:2018-02-13 03:53:49

标签: r function categorical-data mutate

如果这是一个初学者的问题,请原谅我。我对R.相对较新。我正在练习写作功能。我目前正在尝试编写一个函数,该函数采用代表时间的任何数值向量,并将每个观察分类为以下类别:"早晨","下午","晚上","晚上"。所有代表时间的向量都在军事时间。

time_cat <- function(df, column) {
 select(df, column) %>%
 mutate(time_category = ifelse(column %in% 500:1159, "Morning", 
                           ifelse(column %in% 1200:1659, "Afternoon", 
                                  ifelse(column %in% 1700:2059, "Evening", "Night"))))
}

我使用nycflights13包中的航班数据集进行练习。但是,该功能似乎错误地将所有观察分类为&#34;夜晚&#34;类别。

time_cat(flights, "dep_time")
 # A tibble: 336,776 x 2
   dep_time time_category
      <int>         <chr>
 1      517         Night
 2      533         Night
 3      542         Night
 4      544         Night
 5      554         Night
 6      554         Night
 7      555         Night
 8      557         Night
 9      557         Night
10      558         Night
# ... with 336,766 more rows

显然,所有这些观察结果应归类为&#34; Morning&#34;。

有人可以解释一下该代码有什么问题吗?

我将非常感激。

感谢。

2 个答案:

答案 0 :(得分:1)

问题在于,在调用"dep_time"时,它尝试将字符串mutate与一系列数字匹配,而不是将数据框中该名称的列与数字范围。

例如,在下面的代码中,"a" == "b"将第一次调用f"b" == "b"a进行比较。在任何情况下都不使用列bdd <- data.frame(a = c("a", "b", "c"), b = c("A", "B", "C")) f <- function(x) dd %>% mutate(new_column = x == "b") f("a") ## a b new_column ## 1 a A FALSE ## 2 b B FALSE ## 3 c C FALSE f("b") ## a b new_column ## 1 a A TRUE ## 2 b B TRUE ## 3 c C TRUE

time_cat <- function(df, column) {
 column <- sym(column)
 select(df, !!column) %>%
 mutate(time_category = ifelse((!!column) %in% 500:1159, "Morning", 
                           ifelse((!!column) %in% 1200:1659, "Afternoon", 
                                  ifelse((!!column) %in% 1700:2059, "Evening", "Night"))))
}

time_cat(flights, "dep_time")

要解决这个问题,请使用rlang软件包的tidyeval工具:

case_when

您也可能会发现使用time_cat <- function(df, column) { column <- sym(column) df %>% select(!!column) %>% mutate(time_category = case_when((!!column) %in% 500:1159 ~ "Morning", (!!column) %in% 1200:1659 ~ "Afternoon", (!!column) %in% 1700:2059 ~ "Evening", TRUE ~ "Night")) } time_cat(flights, "dep_time") 更方便。此外,通常从管道左侧的输入开始。

{{1}}

答案 1 :(得分:0)

也许你们中的一些人会不同意我的观点,但是我不会使用某个函数,并且会使用data.table库来解决它:

library(data.table)
flights <- as.data.table(flights)

flights[dep_time < 1200, time_cat := "Morning"]
flights[dep_time > 1159 & dep_time < 1700, time_cat := "Afternoon"]
flights[dep_time > 1659 & dep_time < 2100, time_cat := "Evening"]
flights[dep_time > 2059, time_cat := "Night"]