问题:
在数据框中,我想创建一个新列作为现有列的下一个较小值的索引。
例如,数据看起来像这样。它已经安排在item, day
。
item day val
1 1 2 3
2 1 4 2
3 1 5 1
4 2 1 1
5 2 3 2
6 2 5 3
首先,我想在group_by(item)
中使用dplyr
来选择每个项目的子数据框。
然后对于第1行,我向下看行,发现第2行的val
更小。这就是我想要的,所以我记录了与该行对应的day
。第2行类似。
请注意,对于第3行和第6行,它们是相应子数据帧的最后一行,因此没有下一个较小的值。对于第4行和第5行,当我向下看行时,不会有较小的val
。
包含新列的数据框应如下所示。
item day val next.smaller.day
1 1 2 3 4
2 1 4 2 5
3 1 5 1 -1
4 2 1 1 -1
5 2 3 2 -1
6 2 5 3 -1
我想知道是否有任何方法可以使用dplyr
来实现此功能,或使用r
中除for循环之外的任何代码。
我找到了一个询问此问题算法的线程。 Given an array, find out the next smaller element for each element。 它是相关的,并且所提出的算法在时间复杂度方面胜过我的,但我仍然发现在我的场景中很难实现。
谢谢!
更新
这是另一个重新说明我正在寻找的例子。
item day val next.smaller.day
1 1 2 2 5
2 1 4 3 5
3 1 5 1 -1
4 2 1 3 3
5 2 3 1 -1
6 2 5 2 -1
答案 0 :(得分:0)
您可以按项目对数据进行分组,使用diff
函数计算行之间的差异,并检查它是否小于零,然后生成逻辑向量,您可以使用逻辑向量来获取第二天。由于您第二天正在接收,因此您需要使用lead
功能将日期列向前移动,以便它可以匹配您要放置它们的行。
旁注:由于diff
函数创建一个向量,一个元素比原始元素短,并且您将始终将最后一行留在每个组中,我们可以填充{{1} } diff
条件导致的结果。
FALSE
更新:
library(dplyr);
df %>% group_by(item) %>% mutate(smaller = c(diff(val) < 0, F),
next.smaller.day = ifelse(smaller, lead(day), -1)) %>%
select(-smaller)
# Source: local data frame [6 x 4]
# Groups: item [2]
# item day val next.smaller.day
# <int> <int> <int> <dbl>
# 1 1 2 3 4
# 2 1 4 2 5
# 3 1 5 1 -1
# 4 2 1 1 -1
# 5 2 3 2 -1
# 6 2 5 3 -1