在 R 中,像 Solver 这样的计算题
In R , a calculation question like Solver
下面dataframe中有仓库数字,目前知道数据ship_in
和ship_out_forecast
。
现在我想修正 ship_out_forecast
个数字,使其合理(结果如附图中的 'ship_out_forecast_checked')
约束条件如下:
- cumsum(ship_in)-cumsum(ship_out_forecast_checked)>= 0
- ship_out_forecast_checked>0
- 'ship_out_forecast_checked'<='ship_out_forecast'
library(tidyverse)
mdate <- c(44593,44594,44595,44596,44597,44598,44599,44600,44601,44602,44603,44604,44605,44606,44607,44593,44594,44595,44596,44597,44598,44599,44600,44601,44602,44603,44604,44605,44606,44607)
category <- c("A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B")
ship_in <- c(20,0,0,0,5,0,0,0,0,7,0,0,0,0,0,1,0,0,7,30,0,0,0,0,25,0,0,0,0,0)
ship_out_forecast <- c(12,15,13,11,3,5,8,14,8,11,1,9,16,9,3,29,10,28,0,21,12,23,22,23,19,1,2,16,15,9)
warehouse_data <- data.frame(mdate,category,ship_in,ship_out_forecast) %>%
mutate(mdate=as.Date(mdate,origin='1900-1-1'))
使用 作为起点 Reduce_frame
:
Reduce_frame <- function(data, expr, init) {
expr <- substitute(expr)
out <- rep(init[1][NA], nrow(data))
for (rn in seq_len(nrow(data))) {
out[rn] <- init <- eval(expr, envir = data[rn,])
}
out
}
假设你想按 category
进行分组(如果没有,可以很容易地删除),我们可以这样做:
warehouse_data %>%
group_by(category) %>%
mutate(
ending_inventory = Reduce_frame(cur_data(), max(0, init + ship_in - ship_out_forecast), init = 0)
) %>%
ungroup()
# # A tibble: 30 x 5
# mdate category ship_in ship_out_forecast ending_inventory
# <date> <chr> <dbl> <dbl> <dbl>
# 1 2022-02-03 A 20 12 8
# 2 2022-02-04 A 0 15 0
# 3 2022-02-05 A 0 13 0
# 4 2022-02-06 A 0 11 0
# 5 2022-02-07 A 5 3 2
# 6 2022-02-08 A 0 5 0
# 7 2022-02-09 A 0 8 0
# 8 2022-02-10 A 0 14 0
# 9 2022-02-11 A 0 8 0
# 10 2022-02-12 A 7 11 0
# # ... with 20 more rows
下面dataframe中有仓库数字,目前知道数据ship_in
和ship_out_forecast
。
现在我想修正 ship_out_forecast
个数字,使其合理(结果如附图中的 'ship_out_forecast_checked')
约束条件如下:
- cumsum(ship_in)-cumsum(ship_out_forecast_checked)>= 0
- ship_out_forecast_checked>0
- 'ship_out_forecast_checked'<='ship_out_forecast'
library(tidyverse)
mdate <- c(44593,44594,44595,44596,44597,44598,44599,44600,44601,44602,44603,44604,44605,44606,44607,44593,44594,44595,44596,44597,44598,44599,44600,44601,44602,44603,44604,44605,44606,44607)
category <- c("A","A","A","A","A","A","A","A","A","A","A","A","A","A","A","B","B","B","B","B","B","B","B","B","B","B","B","B","B","B")
ship_in <- c(20,0,0,0,5,0,0,0,0,7,0,0,0,0,0,1,0,0,7,30,0,0,0,0,25,0,0,0,0,0)
ship_out_forecast <- c(12,15,13,11,3,5,8,14,8,11,1,9,16,9,3,29,10,28,0,21,12,23,22,23,19,1,2,16,15,9)
warehouse_data <- data.frame(mdate,category,ship_in,ship_out_forecast) %>%
mutate(mdate=as.Date(mdate,origin='1900-1-1'))
使用 Reduce_frame
:
Reduce_frame <- function(data, expr, init) {
expr <- substitute(expr)
out <- rep(init[1][NA], nrow(data))
for (rn in seq_len(nrow(data))) {
out[rn] <- init <- eval(expr, envir = data[rn,])
}
out
}
假设你想按 category
进行分组(如果没有,可以很容易地删除),我们可以这样做:
warehouse_data %>%
group_by(category) %>%
mutate(
ending_inventory = Reduce_frame(cur_data(), max(0, init + ship_in - ship_out_forecast), init = 0)
) %>%
ungroup()
# # A tibble: 30 x 5
# mdate category ship_in ship_out_forecast ending_inventory
# <date> <chr> <dbl> <dbl> <dbl>
# 1 2022-02-03 A 20 12 8
# 2 2022-02-04 A 0 15 0
# 3 2022-02-05 A 0 13 0
# 4 2022-02-06 A 0 11 0
# 5 2022-02-07 A 5 3 2
# 6 2022-02-08 A 0 5 0
# 7 2022-02-09 A 0 8 0
# 8 2022-02-10 A 0 14 0
# 9 2022-02-11 A 0 8 0
# 10 2022-02-12 A 7 11 0
# # ... with 20 more rows