我正在尝试找到一种方法,以识别数据集中介于两个值之间的数字。到目前为止,我的做法是使用ifelse,如下所示:
ifelse(score<=5,1,ifelse(score<=7,2,3))
这种方法可以实现,但我想知道是否有更好的方法来查找5<=R>7,请帮忙提供建议。
谢谢
詹姆斯
我正在尝试找到一种方法,以识别数据集中介于两个值之间的数字。到目前为止,我的做法是使用ifelse,如下所示:
ifelse(score<=5,1,ifelse(score<=7,2,3))
这种方法可以实现,但我想知道是否有更好的方法来查找5<=R>7,请帮忙提供建议。
谢谢
詹姆斯
findInterval
函数基本符合你的需求,但是区间右端点是开区间。通过对所有参数取反可以得到闭区间。
你的代码:
x <- function(score) ifelse(score<=5,1,ifelse(score<=7,2,3))
findInterval
方法:
y <- function(score) 3 - findInterval(-score, -c(7,5))
结果:
> x(1:20)
[1] 1 1 1 1 1 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3
> y(1:20)
[1] 1 1 1 1 1 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3
我赞同@MatthewLundberg的回答,因为我是findInterval的忠实粉丝,但我认为cut函数可能更容易使用。正如他所指出的,在findInterval中进行比较将给出左闭区间,而你想要右闭区间。除了默认标记之外,cut默认提供右闭区间。你可以使用as.numeric去掉标记:
cut(1:10, c(-Inf, 5,7, Inf) )
[1] (-Inf,5] (-Inf,5] (-Inf,5] (-Inf,5] (-Inf,5] (5,7] (5,7] (7, Inf]
[9] (7, Inf] (7, Inf]
Levels: (-Inf,5] (5,7] (7, Inf]
as.numeric( cut(1:10, c(-Inf, 5,7, Inf) ) )
[1] 1 1 1 1 1 2 2 3 3 3
> get_inter <- function(vec, cutvec){ as.numeric(cut(vec, breaks=c(-Inf,cutvec,Inf) ) ) }
> get_inter(1:10, c(5,7) )
[1] 1 1 1 1 1 2 2 3 3 3
labels = FALSE
应该等同于 as.numeric(cut(.))
。 - Blue Magistercut.default
内部的所有粘贴操作。 - IRTFM只需使用矢量化比较:
# generate some repeatable numbers
set.seed(1492)
score <- sample(1:10, 25, replace=TRUE)
# show the numbers
print(score)
[1] 3 3 2 2 1 1 9 6 4 8 7 7 2 6 6 8 2 4 7 10 7 4 2 6 1
# printing the value + compare result just to show that it works
# you can do ifelse((score <= 5 | score > 7), something, somethingelse)
print(data.frame(score=score, tst=(score <= 5 | score > 7)))
score tst
1 3 TRUE
2 3 TRUE
3 2 TRUE
4 2 TRUE
5 1 TRUE
6 1 TRUE
7 9 TRUE
8 6 FALSE
9 4 TRUE
10 8 TRUE
11 7 FALSE
12 7 FALSE
13 2 TRUE
14 6 FALSE
15 6 FALSE
16 8 TRUE
17 2 TRUE
18 4 TRUE
19 7 FALSE
20 10 TRUE
21 7 FALSE
22 4 TRUE
23 2 TRUE
24 6 FALSE
25 1 TRUE
%in%
是一些不错的语法糖:R>x <- 1:10
R>x %in% 5:8
[1] FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE
ifelse
更快的方法,还是更简单的语法,或者完全不同的东西? - TheComeOnMan