r - 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 新手,我已经为此工作了好几天。谢谢!
解决方案
这对你有用吗:
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天的库存
我们需要在每个期末计算库存。所以我创建了一个稍微不同的数据框,其中包含Date
和Incoming
列Inventory
。假设第一行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
这可以很容易地扩展到包括组。这有帮助吗?
推荐阅读
- google-apps-script - 使用带有 ARRAYFORMULA 的自定义 MD5 公式
- makefile - 找不到带有 scipt 的 Makefile 创建临时文件
- javascript - 如何将参数从 redux-saga 观察者发送到 AsyncFunction?
- python - 从批处理文件将参数传递给python脚本
- react-native - 如何在 nativebase 中的所有屏幕上使用通用页脚
- linux - 在 CSV 文件中,我想从 UNIX 文件的第 3 列的 10 个字符中删除前 5 个字符
- excel - VBA:CDbl 忽略逗号小数分隔符
- python - 具有少量 gpus 的多个 cpu 生产者未使用 100% 的 gpus (pytorch)
- python - Python从熊猫列转换为列表?
- wordpress - 简码在 Wordpress 网站上不起作用