我需要实现FIFO算法
I need to realize FIFO algorithm
我有一个像这样的数据框:
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 方法计算余额的数量和价值。当我们销售一件商品时,我们首先按日期销售(table 按操作日期分组)。我们需要计算未售出商品的价值。
我需要通过 FIFO(先进先出)获得运动项目(买卖)的结果及其价值
在我的示例中,结果必须是:
Item A:
Quantity: 11 Value 1000
Item B:
Quantity: 20 Value 1000
Item C:
Quantity: 1000 Value 5000
首先,将数量列转换为包含 positive/negative for buy/sell:
items$Quantity <- items$Quantity * ifelse(items$BuySell=="B",1,-1)
接下来,探索如何使用数据的子集执行逻辑,例如对于项目 B:
x <- items[items$Items == "Item B",]
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) # cumulative 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))
#$Quantity
#[1] 20
#
#$Value
#[1] 1000
接下来我们把then包装成一个函数,这样我们就可以通过数据框的一个子集来调用它:
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
函数将函数应用于数据帧的切片:
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)
这给出了以下 data.frame
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
我有一个像这样的数据框:
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 方法计算余额的数量和价值。当我们销售一件商品时,我们首先按日期销售(table 按操作日期分组)。我们需要计算未售出商品的价值。
我需要通过 FIFO(先进先出)获得运动项目(买卖)的结果及其价值
在我的示例中,结果必须是:
Item A:
Quantity: 11 Value 1000
Item B:
Quantity: 20 Value 1000
Item C:
Quantity: 1000 Value 5000
首先,将数量列转换为包含 positive/negative for buy/sell:
items$Quantity <- items$Quantity * ifelse(items$BuySell=="B",1,-1)
接下来,探索如何使用数据的子集执行逻辑,例如对于项目 B:
x <- items[items$Items == "Item B",]
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) # cumulative 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))
#$Quantity
#[1] 20
#
#$Value
#[1] 1000
接下来我们把then包装成一个函数,这样我们就可以通过数据框的一个子集来调用它:
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
函数将函数应用于数据帧的切片:
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)
这给出了以下 data.frame
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