【问题标题】:tidyverse: row wise calculations by grouptidyverse:按组按行计算
【发布时间】:2019-03-14 16:02:40
【问题描述】:

我正在尝试在 R 中进行库存计算,这需要对每个 Mat-Plant 组合进行逐行计算。这是一个测试数据集 -

df <- structure(list(Mat = c("A", "A", "A", "A", "A", "A", "B", "B"
), Plant = c("P1", "P1", "P1", "P2", "P2", "P2", "P1", "P1"), 
    Day = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L), UU = c(0L, 10L, 
    0L, 0L, 0L, 120L, 10L, 0L), CumDailyFcst = c(11L, 22L, 33L, 
    0L, 5L, 10L, 20L, 50L)), .Names = c("Mat", "Plant", "Day", 
"UU", "CumDailyFcst"), class = "data.frame", row.names = c(NA, 
-8L))

  Mat Plant Day  UU CumDailyFcst
1   A    P1   1   0           11
2   A    P1   2  10           22
3   A    P1   3   0           33
4   A    P2   1   0            0
5   A    P2   2   0            5
6   A    P2   3 120           10
7   B    P1   1  10           20
8   B    P1   2   0           50

我需要一个新字段“EffectiveFcst”,以便 when Day = 1 then EffectiveFcst = CumDailyFcst 和接下来的几天 -

这是所需的输出 -

  Mat Plant Day  UU CumDailyFcst EffectiveFcst
1   A    P1   1   0           11            11
2   A    P1   2  10           22            22
3   A    P1   3   0           33            23
4   A    P2   1   0            0             0
5   A    P2   2   0            5             5
6   A    P2   3 120           10            10
7   B    P1   1  10           20            20
8   B    P1   2   0           50            40

我目前正在使用 for 循环,但实际表超过 300K 行,因此希望使用 tidyverse 执行此操作,以获得更优雅和更快的方法。尝试了以下但没有成功 -

group_by(df, Mat, Plant) %>%
  mutate(EffectiveFcst = ifelse(row_number()==1, CumDailyFcst, 0)) %>%
  mutate(EffectiveFcst = ifelse(row_number() > 1, CumDailyFcst - lag(CumDailyFcst, default = 0) + max(lag(EffectiveFcst, default = 0) - lag(UU, default = 0), 0), EffectiveFcst)) %>%
  print(n = nrow(.))

【问题讨论】:

  • 基本上是max(lag(EffectiveFcst) - lag(UU), 0),即如果差为负,则设为0。
  • 我在想你的代码成功了,但想要更快的代码
  • 有没有可能你改变了单元格 F5?
  • @akrun....不,它不起作用...如果没有循环,这非常棘手...我觉得没有循环甚至不可能...
  • @Nettle 是的,F2、F5 和 F8 等于对应的 CumDailyFcst...基本上每个 Mat-Plant 组合的计算都会重新开始。

标签: r dplyr tidyverse


【解决方案1】:

我们可以从purrr使用accumulate

library(tidyverse)
df %>% 
   group_by(Mat, Plant) %>% 
   mutate(EffectiveFcst =  accumulate(CumDailyFcst - lag(UU, default = 0),  ~ 
          .y , .init = first(CumDailyFcst))[-1] ) 
# A tibble: 8 x 6
# Groups:   Mat, Plant [3]
#  Mat   Plant   Day    UU CumDailyFcst EffectiveFcst
#  <chr> <chr> <int> <int>        <int>         <dbl>
#1 A     P1        1     0           11            11
#2 A     P1        2    10           22            22
#3 A     P1        3     0           33            23
#4 A     P2        1     0            0             0
#5 A     P2        2     0            5             5
#6 A     P2        3   120           10            10
#7 B     P1        1    10           20            20
#8 B     P1        2     0           50            40

【讨论】:

  • 感谢您的回答,但这不是所需的输出。第 3 行和第 6 行的 EffectiveFcst 错误。问题是每次我们“移动”到下一行时,我们都需要从上一行获取更新后的 EffectiveFcst。
  • @Shree 你现在可以检查代码吗?你需要accumulate
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 2014-05-11
  • 1970-01-01
相关资源
最近更新 更多