问题描述
我正在尝试使用 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
的每个单独值进行单独的逻辑测试,但 &&
仅对向量的第一个值运行逻辑测试并返回单个 TRUE
或 FALSE
结果。
看看下面的例子。在 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)"))