vector1 = c(2, 2, 2, 2, 2, 2)
vector2 = c(2, 2, 3, 3, 3, 3)
vector3 = c(2, 2, 1, 2, 2, 2)
Run Code Online (Sandbox Code Playgroud)
我想知道向量中的数字是上升/保持相同还是下降.因此,对于vector1和vector2,它应该是TRUE,而对于vector3它应该是FALSE.简单地说,FALSE如果向量中存在回归,则应该返回.没有编写循环,有没有快速的方法来做到这一点?
Mic*_*ico 25
有一个R称为基本函数is.unsorted,适用于这种情况:
!is.unsorted(vector1)
# [1] TRUE
!is.unsorted(vector2)
# [1] TRUE
!is.unsorted(vector3)
# [1] FALSE
Run Code Online (Sandbox Code Playgroud)
这个函数非常快,因为它几乎直接吸引到编译C代码.
我最初的想法是使用sort和identical,一拉 identical(sort(vector1), vector1),但是这是非常缓慢的; 那说,我认为这种方法可以扩展到更灵活的情况.
如果速度真的至关重要,我们可以跳过一些开销is.unsorted并直接调用内部函数:
.Internal(is.unsorted(vector1, FALSE))
Run Code Online (Sandbox Code Playgroud)
(FALSE传递FALSE给论证strictly).这为小矢量提供了~4倍的加速.
为了了解最终选项的速度,这里有一个基准:
library(microbenchmark)
set.seed(10101)
srtd <- sort(sample(1e6, rep = TRUE)) # a sorted test case
unsr <- sample(1e6, rep = TRUE) #an unsorted test case
microbenchmark(times = 1000L,
josilber = {all(diff(srtd) >= 0)
all(diff(unsr) >= 0)},
mikec = {identical(sort(srtd), srtd)
identical(sort(unsr), unsr)},
baser = {!is.unsorted(srtd)
!is.unsorted(unsr)},
intern = {!.Internal(is.unsorted(srtd, FALSE))
!.Internal(is.unsorted(unsr, FALSE))})
Run Code Online (Sandbox Code Playgroud)
在我的机器上的结果:
# Unit: microseconds
# expr min lq mean median uq max neval cld
# josilber 30349.108 30737.6440 34550.6599 34113.5970 34964.171 155283.320 1000 c
# mikec 93167.836 94183.8865 97119.4493 94852.7530 97528.859 229692.328 1000 d
# baser 1089.670 1168.7400 1322.9341 1296.7375 1347.946 6301.866 1000 b
# intern 514.816 532.4405 576.2867 560.5955 566.236 2456.237 1000 a
Run Code Online (Sandbox Code Playgroud)
所以直接调用内部函数(需要注意的是:你需要确保你的矢量非常干净 - 没有NAs等)比基本R函数提供~2倍的速度,这比使用时快〜30倍diff,这是以我最初选择的速度转动~2倍.
jos*_*ber 19
您可以diff计算元素之间的差异,并all检查它们是否都是非负数:
all(diff(vector1) >= 0)
# [1] TRUE
all(diff(vector2) >= 0)
# [1] TRUE
all(diff(vector3) >= 0)
# [1] FALSE
Run Code Online (Sandbox Code Playgroud)
上面的代码检查,如果所有的向量非递减,你可以更换>= 0与<= 0检查,如果他们不提高.相反,如果您的目标是识别非递减或不递增的向量(也就是说它们在同一向量中没有增加和减少的步骤),则有一个简单的修改:
!all(c(-1, 1) %in% sign(diff(vector1)))
# [1] TRUE
!all(c(-1, 1) %in% sign(diff(vector2)))
# [1] TRUE
!all(c(-1, 1) %in% sign(diff(vector3)))
# [1] FALSE
Run Code Online (Sandbox Code Playgroud)