R中嵌套的if-else循环
我有一个名为“犯罪”的数据框架,其中包含一个“pre_rate”列,表示某项法律实施前的犯罪率。我想使用嵌套的if-else循环将每个速率放在“rate\u category”列中。我有以下代码:R中嵌套的if-else循环,r,if-statement,R,If Statement,我有一个名为“犯罪”的数据框架,其中包含一个“pre_rate”列,表示某项法律实施前的犯罪率。我想使用嵌套的if-else循环将每个速率放在“rate\u category”列中。我有以下代码: crimes$rate_category = with(crimes, ifelse(pre_rate > 0.26 && pre_rate < 0.87, 1, ifelse(pre_rate > 1.04 && pre_rate &l
crimes$rate_category =
with(crimes, ifelse(pre_rate > 0.26 && pre_rate < 0.87, 1,
ifelse(pre_rate > 1.04 && pre_rate < 1.94, 2,
ifelse(pre_rate > 2.03 && pre_rate < 2.96, 3,
ifelse(pre_rate > 3.10 && pre_rate < 3.82, 4,
ifelse(pre_rate > 4.20 && pre_rate < 11.00, 5, "NA"))))))
crimes
但是,当我使用原始数据帧运行循环时,“rate_category”列中的所有级别都被错误地设置为1。上面的循环似乎有什么问题?我建议在时使用
case\u,而不是嵌套ifelse语句。它更容易阅读/理解。但是正如@Marius提到的,您的问题是&
而不是使用&
library(tidyverse)
crimes <- data.frame(pre_rate = c(0.27, 1.91, 2.81, 3.21, 4.80))
crimes %>%
mutate(rate_category = case_when(pre_rate > 0.26 & pre_rate < 0.87 ~ 1,
pre_rate > 1.04 & pre_rate < 1.94 ~ 2,
pre_rate > 2.03 & pre_rate < 2.96 ~ 3,
pre_rate > 3.10 & pre_rate < 3.82 ~ 4,
pre_rate > 4.20 & pre_rate < 11.00 ~ 5))
库(tidyverse)
犯罪率%
当(预处理率>0.26和预处理率<0.87~1,
前置率>1.04,前置率<1.94~2,
前置率>2.03,前置率<2.96~3,
前置率>3.10,前置率<3.82~4,
预制率>4.20,预制率<11.00~5)
为什么不在两个向量中定义下界和上界,然后依靠索引?使用此方法,无需多次写入pre_rate>num1和pre_rate
lowB <- c(0.26, 1.04, 2.03, 3.10, 4.2)
uppB <- c(0.87, 1.94, 2.96, 3.82, 11)
myCategory <- 1:5 ## this can be whatever categories you'd like
crimes$rate_category <- with(crimes, myCategory[pre_rate > lowB & pre_rate < uppB])
lowB您可以使用代数方法来解决您的问题,它应该比ifelse更快:
pre_rate = c(0.27, 1.91, 2.81, 3.21, 4.80)
crimes = data.frame(pre_rate)
crimes$rate = (pre_rate > 0.26 & pre_rate < 0.87)*1 +
(pre_rate > 1.04 & pre_rate < 1.94)* 2 +
(pre_rate > 2.03 & pre_rate < 2.96)* 3 +
(pre_rate > 3.10 & pre_rate < 3.82)* 4 +
(pre_rate > 4.20 & pre_rate < 11.00)* 5
如果您的数据不包含间隙,并且您只需要索引,则可以使用。bincode
:
crimes$rate_category <- .bincode(crimes$pre_rate,
breaks = c(-Inf, 1, 2, 3, 4, Inf))
但是,在您的情况下,您可能只需要上限
(即将预付款利率的值四舍五入,并将其上限设置为5:
crimes$rate_category <- pmin(ceiling(crimes$pre_rate), 5)
#> pre_rate rate_category
#> 1 0.27 1
#> 2 1.91 2
#> 3 2.81 3
#> 4 3.21 4
#> 5 4.80 5
犯罪$rate\u类别pre\u rate\u类别
#> 1 0.27 1
#> 2 1.91 2
#> 3 2.81 3
#> 4 3.21 4
#> 5 4.80 5
可以使用非相等联接和联接时更新,而不是多个嵌套的ifelse()
# OP's sample data set with one out-of-bounds value appended
crimes = data.frame(pre_rate = c(0.27, 1.91, 2.81, 3.21, 4.80, 1.0))
library(data.table)
# specify categories, lower, and upper bounds
bounds <- data.table(
cat = 1:5,
lower = c(0.26, 1.04, 2.03, 3.10, 4.2),
upper = c(0.87, 1.94, 2.96, 3.82, 11)
)
# non-equi join and update on join
setDT(crimes)[bounds, on = .(pre_rate > lower, pre_rate < upper), rate_category := cat][]
请注意,pre-rate
任何给定间隔之外的值都会自动获得一个NA
rate\u类别
。使用&&
时要小心:它只比较向量的第一个元素。&
进行元素级比较,这可能是您想要的。我认为g a字符“NA”
在你的期末考试中,ifelse
会将列转换为字符,从而弄乱列。只需使用NA
,不加引号。你的目标真的是要有差距吗?例如,你想让预设的2为NA吗?@Hugh所有的比率都是8位小数,所以我只是将它们四舍五入到第一百位。会有差距,但不会有差距在任何相关数据中,.between()在这里可能有用。@Hugh根据帮助页面,?dplyr::between
是x>=left&x Correct的快捷方式。但是,从OP的评论来看,这种区别似乎无关紧要。您也可以只包括
library(magrittr)
library(data.table)
rate_category_by_pre_rate <-
data.table(rate_category = c("foo", "bar", "foobar", "baz", "foobie"),
pre_rate = c(1, 2, 3, 4, 11)) %>%
setkey(pre_rate)
crimes %>%
as.data.table %>%
setkey(pre_rate) %>%
rate_category_by_pre_rate[., roll = -Inf]
#> rate_category pre_rate
#> 1: foo 0.27
#> 2: bar 1.91
#> 3: foobar 2.81
#> 4: baz 3.21
#> 5: foobie 4.80
crimes$rate_category <- pmin(ceiling(crimes$pre_rate), 5)
#> pre_rate rate_category
#> 1 0.27 1
#> 2 1.91 2
#> 3 2.81 3
#> 4 3.21 4
#> 5 4.80 5
# OP's sample data set with one out-of-bounds value appended
crimes = data.frame(pre_rate = c(0.27, 1.91, 2.81, 3.21, 4.80, 1.0))
library(data.table)
# specify categories, lower, and upper bounds
bounds <- data.table(
cat = 1:5,
lower = c(0.26, 1.04, 2.03, 3.10, 4.2),
upper = c(0.87, 1.94, 2.96, 3.82, 11)
)
# non-equi join and update on join
setDT(crimes)[bounds, on = .(pre_rate > lower, pre_rate < upper), rate_category := cat][]
pre_rate rate_category
1: 0.27 1
2: 1.91 2
3: 2.81 3
4: 3.21 4
5: 4.80 5
6: 1.00 NA