在数据框中,找到列的每个元素的下一个较小值的索引

时间:2016-07-05 15:43:47

标签: r dplyr

问题:

在数据框中,我想创建一个新列作为现有列的下一个较小值的索引。

例如,数据看起来像这样。它已经安排在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

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