R 在数据帧中,为列的每个元素查找下一个较小值的索引
问题: 在dataframe中,我想创建一个新列作为现有列的下一个较小值的索引 例如,数据如下所示。它已经安排在R 在数据帧中,为列的每个元素查找下一个较小值的索引,r,dplyr,R,Dplyr,问题: 在dataframe中,我想创建一个新列作为现有列的下一个较小值的索引 例如,数据如下所示。它已经安排在项目,日期中 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 首先,我想使用dplyr中的groupby(item)来选择每个项目的子数据帧 然后,对于第1行,我向下查看行,发现第2行的val较小。这就是我想要
项目,日期中
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
首先,我想使用dplyr
中的groupby(item)
来选择每个项目的子数据帧
然后,对于第1行,我向下查看行,发现第2行的val
较小。这就是我想要的,所以我记录了与该行对应的天。第2行类似
请注意,对于第3行和第6行,它们是对应子数据帧的最后一行,因此没有下一个较小的值。对于第4行和第5行,当我向下查看行时,没有更小的val
带有新列的dataframe应该如下所示
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循环之外的任何代码
我发现一条线索在问这个问题的算法。
这是相关的,并且提出的算法在时间复杂度方面优于我的算法,但我仍然发现在我的场景中很难实现
谢谢大家!
更新:
这里有另一个例子来重新说明我在寻找什么
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
您可以按项目对数据进行分组,使用diff
函数计算行与行之间的差异,并检查其是否小于零,这将生成一个逻辑向量,您可以使用该逻辑向量在第二天提取数据。由于您将在第二天取货,因此需要使用lead
功能向前移动day列,以便它能够匹配您要放置它们的行
旁注:由于diff
函数创建了一个比原始元素短一个的向量元素,并且每个组始终保留最后一行,因此我们可以使用FALSE
条件填充diff
结果
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
库(dplyr);
df%>%组(项目)%>%突变(较小=c(差异(val)<0,F),
next.smaller.day=ifelse(较小,领先(天),-1))%>%
选择(-较小)
#来源:本地数据帧[6 x 4]
#分组:项目[2]
#项目日期val下一个较小的日期
#
# 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
更新:
find.next.small vec[-1]),
find.next.minger(ini+1,vec[-1]))
}#递归函数将逐元素遍历向量并找出
#下一个较小值的索引。
df%>%分组依据(项目)%>%变异(next.small.day=天[find.next.small(1,val)],
next.small.day=替换(next.small.day,is.na(next.small.day),-1))
#来源:本地数据帧[6 x 4]
#分组:项目[2]
#
#项目日期val下一个较小的日期
#
# 1 1 2 2 5
# 2 1 4 3 5
# 3 1 5 1 -1
# 4 2 1 1 -1
# 5 2 3 2 -1
# 6 2 5 3 -1
您可以按项目对数据进行分组,使用diff
函数计算行间差异,并检查其是否小于零,这将生成一个逻辑向量,您可以使用该逻辑向量在第二天提取。由于您将在第二天取货,因此需要使用lead
功能向前移动day列,以便它能够匹配您要放置它们的行
旁注:由于diff
函数创建了一个比原始元素短一个的向量元素,并且每个组始终保留最后一行,因此我们可以使用FALSE
条件填充diff
结果
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
库(dplyr);
df%>%组(项目)%>%突变(较小=c(差异(val)<0,F),
next.smaller.day=ifelse(较小,领先(天),-1))%>%
选择(-较小)
#来源:本地数据帧[6 x 4]
#分组:项目[2]
#项目日期val下一个较小的日期
#
# 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
更新:
find.next.small vec[-1]),
find.next.minger(ini+1,vec[-1]))
}#递归函数将逐元素遍历向量并找出
#下一个较小值的索引。
df%>%分组依据(项目)%>%变异(next.small.day=天[find.next.small(1,val)],
next.small.day=替换(next.small.day,is.na(next.small.day),-1))
#来源:本地数据帧[6 x 4]
#分组:项目[2]
#
#项目日期val下一个较小的日期
#
# 1 1 2 2 5
# 2 1 4 3 5
# 3 1 5 1 -1
# 4 2 1 1 -1
# 5 2 3 2 -1
# 6 2 5 3 -1
谢谢您的回复。您所做的在给定的示例中起作用。但是,下一个较小的值可能不在下一行中。例如,如果val
是2,3,1
并且day
是2,4,5
,我希望输出是5,5,-1
。您知道如何实现此功能吗?请参阅更新。您可以编写一个递归函数来查找下一个较小值的索引,然后使用dplyr
函数应用它。非常感谢!我试图写一个函数来实现我的目标,但我想不出来。