R 我需要实现FIFO算法
我有一个数据框,如:R 我需要实现FIFO算法,r,dataframe,fifo,R,Dataframe,Fifo,我有一个数据框,如: items = data.frame( Items = c('Item A', 'Item B','Item A','Item A','Item A','Item B','Item B','Item A','Item C'), Quantity = c(5,100,4,7,10,50,30,1,1000), BuySell = c('B','B','B','S','B','S','S','S','B'), Price = c(100,50,110,130,9
items = data.frame(
Items = c('Item A', 'Item B','Item A','Item A','Item A','Item B','Item B','Item A','Item C'),
Quantity = c(5,100,4,7,10,50,30,1,1000),
BuySell = c('B','B','B','S','B','S','S','S','B'),
Price = c(100,50,110,130,90,45,60,120,5)
)
items$Value = items$Quantity * items$Price
我需要按名称对项目进行分组,并使用FIFO方法计算余额的金额和价值。当我们销售商品时,我们首先按日期销售(表按操作日期分组)。我们需要计算未售出物品的价值
我需要通过FIFO(先进先出)获得移动项目(购买和出售)的结果及其价值
在我的示例中,结果必须是:
首先,将数量列转换为包含买入/卖出的正/负数量:
items$Quantity <- items$Quantity * ifelse(items$BuySell=="B",1,-1)
接下来,我们将其包装成一个函数,以便我们可以通过数据帧的子集调用它:
calculate.lv <- function(x){
unsold <- sum(x$Quantity)
x <- x[seq(nrow(x),1,-1),] # reverse order (unsold items are at bottom)
x <- x[x$Quantity > 0,] # consider buy only
x$cs <- cumsum(x$Quantity) # cummulative bought amount
x$cs <- pmin(x$cs, unsold)
if(nrow(x) > 1) x[-1,"cs"] <- diff(x$cs) # cs column now holds the amount relevant for cost calculation
list("Quantity" = unsold, "Value" = sum(x$cs * x$Price))
}
calculate.lv(items[items$Items=="Item C",])
#$Quantity
#[1] 1000
#
#$Value
#[1] 5000
by(items, list(items$Items), calculate.lv)
#: Item A
#$Quantity
#[1] 11
#
#$Value
#[1] 1010
#
#------------------------------------------------------------
#: Item B
#$Quantity
#[1] 20
#
#$Value
#[1] 1000
#
#------------------------------------------------------------
#: Item C
#$Quantity
#[1] 1000
#
#$Value
#[1] 5000
#
使用
dplyr
和tidyr
的另一个选项是
library(dplyr)
library(tidyr)
items <- items %>%
group_by(Items) %>%
mutate(index = 1:n()) %>%
spread(BuySell, Quantity, fill = 0) %>%
arrange(Items, index) %>%
mutate(TotalStock = cumsum(B) - cumsum(S),
Sold = case_when(B == 0 ~ 0, # Nothing bought - cannot be sold
cumsum(B) < sum(S) ~ B, # Total items bought is smaller than total item sold - everything is sold
sum(S) < (cumsum(B) - B) ~ 0, # Total sum is smaller than total amount bought excluding the current buy - nothing sold
TRUE ~ B - (cumsum(B) - sum(S))),
InStock = B - Sold)
这可以概括为
items %>%
summarize(Value = sum(InStock * Price),
TotalStock = sum(InStock))
# A tibble: 3 x 3
# Items Value TotalStock
# <fct> <dbl> <dbl>
# 1 Item A 1010 11
# 2 Item B 1000 20
# 3 Item C 5000 1000
项目%>%
汇总(价值=总额(库存*价格),
总库存=总和(库存))
#一个tibble:3x3
#物品价值总存量
#
#1项目A 1010 11
#2项目B 1000 20
#3项目C 5000 1000
如何获得这些数量/值?例如,Value 130
来自哪里?与项目B类似
。。。为什么数量20
?因为买:(数量)100,卖50+30我在这个例子中看不到任何日期。真的很难遵循你的逻辑。您应该通过编辑您的问题来清楚地解释@Sotos问题的步骤。我们买卖商品(A、B、C项)。买卖以不同的价格进行。当销售以前购买的产品时,该产品将从仓库中扣除。其余货物按剩余货物的购买价格估算。销售首先从同一名称的第一批购货中借记,然后从第二批购货中借记,依此类推。当TotalStock一开始为负数时,有没有办法使其正常工作?我正在处理一个案例,其中a项的初始股票可以是负数(例如,交易中的卖空),但代码却非常出色=)
calculate.lv <- function(x){
unsold <- sum(x$Quantity)
x <- x[seq(nrow(x),1,-1),] # reverse order (unsold items are at bottom)
x <- x[x$Quantity > 0,] # consider buy only
x$cs <- cumsum(x$Quantity) # cummulative bought amount
x$cs <- pmin(x$cs, unsold)
if(nrow(x) > 1) x[-1,"cs"] <- diff(x$cs) # cs column now holds the amount relevant for cost calculation
list("Quantity" = unsold, "Value" = sum(x$cs * x$Price))
}
calculate.lv(items[items$Items=="Item C",])
#$Quantity
#[1] 1000
#
#$Value
#[1] 5000
by(items, list(items$Items), calculate.lv)
#: Item A
#$Quantity
#[1] 11
#
#$Value
#[1] 1010
#
#------------------------------------------------------------
#: Item B
#$Quantity
#[1] 20
#
#$Value
#[1] 1000
#
#------------------------------------------------------------
#: Item C
#$Quantity
#[1] 1000
#
#$Value
#[1] 5000
#
library(dplyr)
library(tidyr)
items <- items %>%
group_by(Items) %>%
mutate(index = 1:n()) %>%
spread(BuySell, Quantity, fill = 0) %>%
arrange(Items, index) %>%
mutate(TotalStock = cumsum(B) - cumsum(S),
Sold = case_when(B == 0 ~ 0, # Nothing bought - cannot be sold
cumsum(B) < sum(S) ~ B, # Total items bought is smaller than total item sold - everything is sold
sum(S) < (cumsum(B) - B) ~ 0, # Total sum is smaller than total amount bought excluding the current buy - nothing sold
TRUE ~ B - (cumsum(B) - sum(S))),
InStock = B - Sold)
items
# A tibble: 9 x 9
# Groups: Items [3]
# Items Price Value index B S TotalStock Sold InStock
# <fct> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 Item A 100 500 1 5 0 5 5 0
# 2 Item A 110 440 2 4 0 9 3 1
# 3 Item A 130 910 3 0 7 2 0 0
# 4 Item A 90 900 4 10 0 12 0 10
# 5 Item A 120 120 5 0 1 11 0 0
# 6 Item B 50 5000 1 100 0 100 80 20
# 7 Item B 45 2250 2 0 50 50 0 0
# 8 Item B 60 1800 3 0 30 20 0 0
# 9 Item C 5 5000 1 1000 0 1000 0 1000
items %>%
summarize(Value = sum(InStock * Price),
TotalStock = sum(InStock))
# A tibble: 3 x 3
# Items Value TotalStock
# <fct> <dbl> <dbl>
# 1 Item A 1010 11
# 2 Item B 1000 20
# 3 Item C 5000 1000