创建新的 R 数据帧变量时使用前一行值

Using previous row values when creating new R dataframe variable

对于 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 等等。

主要问题是滞后函数不允许为您正在创建的同一列获取前一行的值,它必须是数据中已经存在的列。我想通过先创建计算列然后添加第二个计算步骤来分步进行,但无法完全解决。

最后,我知道使用 for 循环可能是一种解决方案,但想知道是否有其他方法?我的数据按额外的列分组,不确定 for 循环是否适用于分组数据行?

感谢您的帮助:)

也许 cummax 函数会有帮助

mutate(calc=pmax(cummax(current+inflow-outflow),inflow))
# 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返回一个向量。
  • 该列表有 6 个条目,因为它包含初始值,我们要删除它。

最后两个步骤在顶部的完整示例中汇集在一起​​。