问题描述
我现在在外汇项目中工作,我在途中发现问题。我试图找出什么时候是最后一次当前值如此之高或如此之低。
起初,我尝试通过这种方式进行操作:
length(c(1:10)) - max(which(c(1:10) <= 6))
即如果我们考虑向量c(1:10,6)
,则上述函数的输出将为4。这意味着6是自4个间隔以来的最大值。
所以我现在的目标是将上述功能实现为dplyr::mutate
方法。那就是事情失控的地方……使用runner
包中的runner
函数,我可以用值及其滞后时间创建小标题:
# A tibble: 11 x 2
value `runner(value,lag = 1)`
<dbl> <list>
1 9 <dbl [0]>
2 7 <dbl [1]>
3 4 <dbl [2]>
4 1 <dbl [3]>
5 5 <dbl [4]>
6 2 <dbl [5]>
7 5 <dbl [6]>
8 4 <dbl [7]>
9 1 <dbl [8]>
10 6 <dbl [9]>
11 6 <dbl [10]>
但是无论如何,我都无法将当前列表中的值编号与运行器列相关联。我正在尝试类似purrr:map
或sapply
之类的事情,但仍然会引用整个专栏。我也尝试实现dplyr::rowWise
,但也没有帮助。
我觉得自己正在研究解决方案,并且可以很容易地做到这一点。如果有一些魔术包可以帮助我快速解决问题,我将非常感谢您的帮助。但是我仍然想知道在这种情况下是否有办法将当前行值而不是整个列关联起来。
我还试图将其关闭为一个整齐的用户自定义函数,如果您可以将其指向该方向,那将是另一个优点。
解决方法
也许您正在寻找类似的东西?
last_below <- function(x)
{
sapply(seq(x),function(i) {
y <- i - rev(which(x[i] >= cummax(x)))[1]
if(y < 0) 0 else y
})
}
所以你可以做
library(dplyr)
df <- data.frame(x = c(1:10,6,4,5,2))
df %>% mutate(y = last_below(x))
#> x y
#> 1 1 0
#> 2 2 0
#> 3 3 0
#> 4 4 0
#> 5 5 0
#> 6 6 0
#> 7 7 0
#> 8 8 0
#> 9 9 0
#> 10 10 0
#> 11 6 5
#> 12 4 8
#> 13 5 8
#> 14 2 12
由reprex package(v0.3.0)于2020-08-24创建
,绝对可以使用runner
完成。
请注意,function(x)
中的runner
是针对每个累积进行评估的-尝试runner(vec)
查看结果(列表)。想象一下,该列表的每个元素都是一个步骤,并且对每个步骤执行function(x)
。
想象一下,对于一个步骤(例如第十个步骤),您需要查找在电流符合条件之前的观察次数。
library(runner)
set.seed(1)
# dummy data
x <- round(cumsum(rnorm(10)))
current_idx <- 10
current_x <- x[current_idx]
up_to_current <- x[-current_idx]
current_idx - which(up_to_current == current_x)
# [1] 2 5
上面的代码可以是function(x)
的主体-“远前的”匹配当前条件之前的条件
runner(
vec,function(x) {
# current index
current_idx <- length(x)
# current value
current_x <- x[current_idx]
# values up to current
up_to_current <- x[-current_idx]
# how many observations since last condition matching
current_idx - which(up_to_current == current_x)
}
)
以上返回一个列表,因为function(x)
的输出长度不同。如果返回单个值,则将返回向量。
P.S。要在当前观察之后 找到匹配条件的索引,您将需要包括rev(vec)
并处理索引差异。
享受!
,由于@ allan-cameron的回答,我找到了解决方案:
last_below <- function(x) {
sapply(
seq(x),function(i) {
(i - tail(which(x[0:(i-1)] <= x[i]),1))[1]
}
)
}
通过致电:
a %>%
mutate(b = last_below(value))
我得到输出:
# A tibble: 11 x 2
value b
<dbl> <int>
1 9 NA
2 7 NA
3 4 NA
4 1 NA
5 5 1
6 2 2
7 5 1
8 4 2
9 1 5
10 6 1
11 6 1