对于我的 R 数据框问题,我真的很感激。找不到类似的帖子,所以如果它已经存在,请分享!
我有以下数据:
mydata <- data.frame(inflow=c(50,60,55,70,80),
outflow=c(70,80,70,65,65),
current=c(100,100,100,100,100))
我想创建一个新列,它的作用类似于:
mutate(calc=pmax(lag(calc,default=current)+inflow-outflow,inflow))
它基本上创建了一个名为 calc 的新列,该列在 a) calc 的前一行值加上该行的流入减去流出或 b) 该行的流入值的最大值之间进行选择。 pmax 是一个名为 rmpfr 的包中的函数,它选择每行给定列中的最大值。
所以我的结果将是:row1 = max(100+50-70, 50) 即 80,row2 = max(80+60-80,60) 即 60,依此类推。
主要问题是滞后函数不允许采用您正在创建的同一列的前一行值,它必须是数据中已经存在的列。我想通过先创建 calc 列然后添加第二个计算步骤来分步完成,但无法完全解决。
最后,我知道使用 for 循环可能是一种解决方案,但想知道是否有不同的方法?我的数据按额外的列分组,并且不确定 for 循环是否适用于分组的数据行?
感谢您的帮助:)
答案 0 :(得分:0)
也许 cummax 函数会有所帮助
mutate(calc=pmax(cummax(current+inflow-outflow),inflow))
答案 1 :(得分:0)
# I don't define the current column, as this is handled with the .init argument of accumulate2
mydata <- data.frame(
inflow=c(50,60,55,70,80),
outflow=c(70,80,70,65,65)
)
# define your recursive function
flow_function <- function(current, inflow, outflow){
pmax(inflow, inflow - outflow + current)
}
mydata %>%
mutate(result = accumulate2(inflow, outflow, flow_function, .init = 100)[-1] %>% unlist)
# inflow outflow result
# 1 50 70 80
# 2 60 80 60
# 3 55 70 55
# 4 70 65 70
# 5 80 65 85
细节
purrr::accumulate
系列函数旨在执行递归计算。
accumulate
可以处理采用前一个值加上另一列中的值的函数,而 accumulate2
允许第二个附加列。您的情况属于后者。
accumulate2
需要以下参数:
.x
- 计算的第一列。.y
- 计算的第二列。.f
- 要递归应用的函数:这应该有三个参数,第一个是递归参数。.init
-(可选)用作第一个参数的初始值。所以在你的情况下,传递给 .f
的函数是
# define your recursive function
flow_function <- function(current, inflow, outflow){
pmax(inflow, inflow - outflow + current)
}
我们首先测试这在 dplyr::mutate
之外产生了什么
# note I don't define the current column, as this is handled with the .init argument
mydata <- data.frame(
inflow=c(50,60,55,70,80),
outflow=c(70,80,70,65,65)
)
purrr::accumulate2(mydata$inflow, mydata$outflow, flow_function, .init = 100)
# returns
# [[1]]
# [1] 100
#
# [[2]]
# [1] 80
#
# [[3]]
# [1] 60
#
# [[4]]
# [1] 55
#
# [[5]]
# [1] 70
#
# [[6]]
# [1] 85
所以关于返回值有两点需要注意:
unlist
返回一个向量。这两个最后的步骤在顶部的完整示例中汇总在一起。