R 中的 ifelse 语句给出了不正确的值

问题描述

我正在尝试使用 ifelse 语句根据计算平均值的值提供“消息”。

这是我的代码。我没有收到错误消息,但睡眠水平不在正确的位置。

summary_sleep<-sleep_day %>%
group_by(Id)%>%
summarise(max_slept = max(TotalMinutesAsleep),mean_sleep=mean(TotalMinutesAsleep),sum_sleep=sum(TotalMinutesAsleep),number_sleep_entries=length(TotalMinutesAsleep))


summary_sleep$level_of_sleep = 
ifelse(summary_sleep$mean_sleep >= 460,"Too much sleep (OVER 460)",ifelse(summary_sleep$mean_sleep >= 360 && summary_sleep$mean_sleep 
<=459,"Good sleep (360-460)",ifelse(summary_sleep$mean_sleep >= 200 && summary_sleep$mean_sleep 
<=360,"Bad sleep (200-360)",ifelse(summary_sleep$mean_sleep >0 && summary_sleep$mean_sleep <200,"Bad sleep (0-200)"))))
ID mean_sleep level_of_sleep
1 294.0000 睡个好觉(360-460)
2 61.000 睡个好觉(360-460)
3 506.1786 睡眠过多(超过 460)

解决方法

对于复杂的条件,可能需要 case_when(或 ifelse)。在您的情况下,条件只是单个数字列的范围,您可以使用 cut 函数:

summary_sleep$level_of_sleep = cut(summary_sleep$mean_sleep,breaks = c(0,200,360,460,Inf),labels = c("Bad sleep (0-200)","Bad sleep (200-360)","Good sleep (360-460)","Too much sleep (OVER 460)"),include.lowest=TRUE)

默认情况下,中断将在右侧关闭并在左侧打开。要扭转这种情况,请使用参数 right=FALSE

关于您的 ifelse 语句:我认为由于使用 && 而不是 &,您得到的值不正确。您希望对 mean_sleep 的每个单独值进行单独的逻辑测试,但 && 仅对向量的第一个值运行逻辑测试并返回单个 TRUEFALSE结果。

看看下面的例子。在 Example 1 中,& 版本为我们提供了针对 x 的每个值的单独逻辑测试,但 && 仅提供了使用 {{ 的第一个值的单个逻辑测试1}}。由于 x,结果为 x[1]=1。在 FALSE 中,我重新排列了 Example 2 以便值 5 排在最前面。 5 满足条件,所以 x 现在返回 &&

TRUE

以及在数据框中使用的示例。请注意,在第二种情况下,我们首先对数据框进行排序:

# Example 1
x = 1:10

x >= 4 & x <= 6
#>  [1] FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE

x >= 4 && x <= 6
#> [1] FALSE

# Example 2
x = c(5,1:4,6:10)

x >= 4 & x <= 6
#>  [1]  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE

x >= 4 && x <= 6
#> [1] TRUE

请参阅 this SO answer 以了解在对值向量进行操作时为什么应该使用 library(tidyverse) mtcars %>% select(mpg) %>% slice(1:10) %>% mutate( `&&` = mpg >= 19 && mpg <= 21,`&` = mpg >= 19 & mpg <= 21,`mpg&&` = ifelse(mpg >= 19 && mpg <= 21,"Mid MPG","Other"),`mpg&` = ifelse(mpg >= 19 & mpg <= 21,"Other") ) #> mpg && & mpg&& mpg& #> Mazda RX4 21.0 TRUE TRUE Mid MPG Mid MPG #> Mazda RX4 Wag 21.0 TRUE TRUE Mid MPG Mid MPG #> Datsun 710 22.8 TRUE FALSE Mid MPG Other #> Hornet 4 Drive 21.4 TRUE FALSE Mid MPG Other #> Hornet Sportabout 18.7 TRUE FALSE Mid MPG Other #> Valiant 18.1 TRUE FALSE Mid MPG Other #> Duster 360 14.3 TRUE FALSE Mid MPG Other #> Merc 240D 24.4 TRUE FALSE Mid MPG Other #> Merc 230 22.8 TRUE FALSE Mid MPG Other #> Merc 280 19.2 TRUE TRUE Mid MPG Mid MPG mtcars %>% select(mpg) %>% slice(1:10) %>% arrange(mpg) %>% mutate( `&&` = mpg >= 19 && mpg <= 21,"Other") ) #> mpg && & mpg&& mpg& #> Duster 360 14.3 FALSE FALSE Other Other #> Valiant 18.1 FALSE FALSE Other Other #> Hornet Sportabout 18.7 FALSE FALSE Other Other #> Merc 280 19.2 FALSE TRUE Other Mid MPG #> Mazda RX4 21.0 FALSE TRUE Other Mid MPG #> Mazda RX4 Wag 21.0 FALSE TRUE Other Mid MPG #> Hornet 4 Drive 21.4 FALSE FALSE Other Other #> Datsun 710 22.8 FALSE FALSE Other Other #> Merc 230 22.8 FALSE FALSE Other Other #> Merc 240D 24.4 FALSE FALSE Other Other 而不是 & 的更多详细信息,其中您希望对每个值进行单独的逻辑测试。 (另外,请注意,在您的示例中,第三个条件看起来应该是 &&,而不是 < 360。)

,

您可能正在寻找case_when

library(dplyr)
summary_sleep %>% mutate(
 level_of_sleep = case_when(
    mean_sleep >= 460 ~ "Too much sleep (OVER 460)",mean_sleep >= 360 & mean_sleep <=459 ~ "Good sleep (360-460)",mean_sleep >= 200 & mean_sleep <360 ~ "Bad sleep (200-360)",mean_sleep > 0 & mean_sleep <200 ~ "Bad sleep (0-200)"))