Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 基于现有列在数据框中创建新的累计列_R_Dataframe_Dplyr_Purrr - Fatal编程技术网

R 基于现有列在数据框中创建新的累计列

R 基于现有列在数据框中创建新的累计列,r,dataframe,dplyr,purrr,R,Dataframe,Dplyr,Purrr,我不久前创建了这个主题:基于现有列计算数据框中的新列。我现在正在寻找类似的东西,但有一点区别。一、 同样,请使用此数据集 df=tibble(article=rep("article one",5), week=c(1,2,3,4,5), sales=20, purchase=c(5,0,5,5,0), stock=c(50)) # A tibble: 5 x 5 article week sales purchase stock <chr&

我不久前创建了这个主题:基于现有列计算数据框中的新列。我现在正在寻找类似的东西,但有一点区别。一、 同样,请使用此数据集

df=tibble(article=rep("article one",5), 
week=c(1,2,3,4,5), 
sales=20, 
purchase=c(5,0,5,5,0), 
stock=c(50))

# A tibble: 5 x 5
  article      week sales purchase stock
  <chr>       <dbl> <dbl>    <dbl> <dbl>
1 article one     1    20        5    50
2 article one     2    20        0    50
3 article one     3    20        5    50
4 article one     4    20        5    50
5 article one     5    20        0    50

我们可以使用
cumsum
lag

library(dplyr)
df %>%
  group_by(article) %>%
  mutate(stock_over_time =  lag(stock + cumsum(lead(purchase) - sales),
       default = first(stock)),
     stock_over_time = case_when(stock_over_time < 0 
           ~ 0 - (sales * 1/4) + purchase, TRUE ~ stock_over_time)) %>%
  ungroup

不过,这种逻辑是否适用于其他行?我不认为“第6行”会看到第5行计算的随时间变化的
stock\u
。我认为需要一个循环或类似于
purr::acculate
的东西,因为每行的销售额取决于当时的库存状况。@JonSpring我也在用
acculate
的方式思考。对于当前的示例,我认为,cumsum应该job@JonSpring我想更新应该可以解决你的问题mentioned@lucaskr使用
accumulate
是可能的,但我认为
for
循环会更容易、更简单readable@lucaskr我用Accumerate更新了解决方案在此之后您希望发生什么,例如,在“第6行”中?比如说,第5行的销售额增加了20,在0.25的降幅后减为5。如果
stock\u over\u time
变成-5或-10?
stock\u over\u time
会变成-10
50 - 20 + 0 = 30
30 - 20 + 5 = 15
15 - 20 + 5 = 0
0 - (20 * 1/4) + 0 = -5
library(dplyr)
df %>%
  group_by(article) %>%
  mutate(stock_over_time =  lag(stock + cumsum(lead(purchase) - sales),
       default = first(stock)),
     stock_over_time = case_when(stock_over_time < 0 
           ~ 0 - (sales * 1/4) + purchase, TRUE ~ stock_over_time)) %>%
  ungroup
# A tibble: 5 x 6
#  article      week sales purchase stock stock_over_time
#  <chr>       <dbl> <dbl>    <dbl> <dbl>           <dbl>
#1 article one     1    20        5    50              50
#2 article one     2    20        0    50              30
#3 article one     3    20        5    50              15
#4 article one     4    20        5    50               0
#5 article one     5    20        0    50              -5
f1 <- function(dat) {
   dat$stock_over_time <- NA_real_
   dat$stock_over_time[1] <- dat$stock[1]
   for(i in 2:nrow(dat)) {
         
      dat$stock_over_time[i] <- dat$stock_over_time[i-1] - 
                      dat$sales[i] + dat$purchase[i]
         if(dat$stock_over_time[i] < 0 ) {
             dat$stock_over_time[i] <- dat$stock_over_time[i-1] - 
                 (dat$sales[i]* 1/4) + dat$purchase[i]
          }  
   }
   return(dat)
 }


unsplit(lapply(split(df, df$article), f1), df$article)
# A tibble: 5 x 6
#  article      week sales purchase stock stock_over_time
#  <chr>       <dbl> <dbl>    <dbl> <dbl>           <dbl>
#1 article one     1    20        5    50              50
#2 article one     2    20        0    50              30
#3 article one     3    20        5    50              15
#4 article one     4    20        5    50               0
#5 article one     5    20        0    50              -5
library(purrr)
f1 <- function(x, y, z) {
         tmp <- x - y + z
         if(tmp < 0) {
            tmp <- x - (y* 1/4) + z
            }
         
         return(tmp)
         }

}


df %>% 
  group_by(article) %>%
  mutate(stock_over_time = accumulate2(sales, 
     lead(purchase, default = last(purchase)), f1, .init = first(stock)) %>%
                    flatten_dbl() %>%
                    head(-1)) %>%
  ungroup
# A tibble: 5 x 6
#  article      week sales purchase stock stock_over_time
#  <chr>       <dbl> <dbl>    <dbl> <dbl>           <dbl>
#1 article one     1    20        5    50              50
#2 article one     2    20        0    50              30
#3 article one     3    20        5    50              15
#4 article one     4    20        5    50               0
#5 article one     5    20        0    50              -5