首页 > 解决方案 > R根据前面的结果逐组计算

问题描述

在此处输入图像描述我想按组找出每个时期有多少天没有供应以及有多少天有供应,我正在考虑创建一个“天”的新变量。起初,我计算了两个相邻日期之间的时间间隔“DateDiff”,然后我使用时间间隔“DateDiff”减去了之前的 SupplyDayslag(SupplyDays)获取“DaysLeft”,如果DaysLeft>0,表示缺货,如果DaysLeft<0,表示还有剩余,可以在接下来的几天使用。但这只是与上一行相比,因此还需要做更多的工作。听起来很复杂。但我的目的是找出每个时期有多少天没有供应,有多少天有供应。问题是将来只能使用以前的剩余耗材,而将来的剩余耗材不能用于过去,所以每一步计算都是基于之前的结果,并且cumsum()不适用于我的情况。每组的“Days”的第一个值等于“DaysLeft”。那么如果之前的“Days”<0,那么现在的“Days”应该是现在的“DaysLeft”加上之前的“Days”来抵消过去剩余的供给,如果之前的“Days”>0,那么现在的“Days”等于现在的“DaysLeft”。

df <- data.frame(Group = c(3, 3, 1, 2, 1, 2, 1, 3, 1, 1), 
                 Date = c(20190102, 20190207, 20190309, 20190417, 20190507, 20190610, 20190707, 20190808, 20190907, 20191018),
                 SupplyDays = c(80,9,40,7,35,7,2,60,1,5))

我尝试使用mutate(),但是 mutate 函数不能告诉新变量本身,所以它不能检查 >0 或 <0。然后我创建了一个循环,但循环有时有效,有时无效。而且我不知道如何在循环中分组。

df$Days[1] <- df$DaysLeft[1]
for (i in 2:length(df$DaysLeft)){
    if (df$Days[i-1]>=0){
        df$Days[i]<-df$DaysLeft[i]
    } else {
   df$Days[i]<-(df$DaysLeft[i]+df$Days[i-1])
  }
}

如果您有任何想法,我将不胜感激!我是 R 新手,我已经为此工作了好几天。谢谢!

标签: r

解决方案


这对你有用吗:

library(dplyr)
library(tidyr)

df <- df %>%
  arrange(Group) %>% # for convenience
  mutate(Date = as.Date(as.character(Date), "%Y%m%d")) %>% # coerce dates to Date format
  group_by(Group) %>% 
  mutate(DateDiff = Date - lag(Date, 1)) %>% # calculate time difference with previous row
  mutate(DateDiff = replace_na(DateDiff, 0)) %>% # replace NA with 0
  mutate(DaysLeft = DateDiff - lag(SupplyDays,1)) %>%
  mutate(DaysLeft = replace_na(DaysLeft, 0)) %>%  # replace NA with 0
  mutate(Days = ifelse(lag(DaysLeft, 1) < 0, DaysLeft + lag(DaysLeft, 1), DaysLeft)) %>%
  mutate(Days = replace_na(Days, 0)) # replace NA with 0

有了这个输出:

> df
# A tibble: 10 x 6
# Groups:   Group [3]
   Group Date       SupplyDays DateDiff DaysLeft  Days
   <dbl> <date>          <dbl> <drtn>   <drtn>   <dbl>
 1     1 2019-03-09         40   0 days   0 days     0
 2     1 2019-05-07         35  59 days  19 days    19
 3     1 2019-07-07          2  61 days  26 days    26
 4     1 2019-09-07          1  62 days  60 days    60
 5     1 2019-10-18          5  41 days  40 days    40
 6     2 2019-04-17          7   0 days   0 days     0
 7     2 2019-06-10          7  54 days  47 days    47
 8     3 2019-01-02         80   0 days   0 days     0
 9     3 2019-02-07          9  36 days -44 days   -44
10     3 2019-08-08         60 182 days 173 days   129

更新

周末我在考虑这个问题,这可能有助于以不同的方式解决这个问题。我们正在处理库存/消耗问题,所以这里有一个非常简单的方法。我们需要有正确的定义才能使它起作用:

  • 进货:期初到达的材料。我认为你SupplyDays的正是这个。
  • 消耗:期间我们每天消耗1天的库存

我们需要在每个期末计算库存。所以我创建了一个稍微不同的数据框,其中包含DateIncomingInventory。假设第一行period: 0只有一个现有库存。然后Inventory成为我已经拥有的(data$Inventory [i - 1]),在此期间传入的(data$Incoming[i])和减去我正在消耗的(as.numeric(data$DateDiff[i]))的总和。

data <- tibble(Date = c(20190309, 20190507, 20190707, 20190907, 20191018, 20191210, 20200120),
             Incoming = c(0, 35, 27, 108, 5, 12, 30),
             Inventory = c(40, 0, 0, 0, 0, 0, 0))

tibble需要一些工作:

data <- data %>%
  mutate(Date = as.Date(as.character(Date), "%Y%m%d")) %>%
  mutate(DateDiff = Date - lag(Date, 1))  %>%# calculate time difference with previous row
  mutate(DateDiff = replace_na(DateDiff, 0))

而且因为我需要以不同于其他行的方式对待第一行,所以我需要使用 for 循环:

for (i in seq_len(nrow(data))) {
  if (i == 1) {
    data$Inventory [i] <- data$Inventory [i] + data$Incoming[i]
  } else {
    data$Inventory [i] <- data$Inventory [i - 1] + data$Incoming[i] - as.numeric(data$DateDiff[i])
  }
}

有了这个输出:

> data
# A tibble: 7 x 4
  Date       Incoming Inventory DateDiff
  <date>        <dbl>     <dbl> <drtn>  
1 2019-03-09        0        40  0 days 
2 2019-05-07       35        16 59 days 
3 2019-07-07       27       -18 61 days 
4 2019-09-07      108        28 62 days 
5 2019-10-18        5        -8 41 days 
6 2019-12-10       12       -49 53 days 
7 2020-01-20       30       -60 41 days 

这可以很容易地扩展到包括组。这有帮助吗?


推荐阅读