2016-04-13 19 views
2

qty sütununu koşulsuz olarak 0'ın alt sınırıyla silmeyi ve siparişin yerine getirilip getirilmediğini belirtmek için bir gösterge sütunu eklemek istiyorum. Birden çok öğem var ve bunu dplyr::group_by kullanarak her bir öğe için yapmak istiyorum. Sadece bir grup gösterilmektedir.dplyr ile koşullu cumsum

df <- data.frame(item = c(rep('a', 10)), 
       date = seq(as.Date('2014-01-01'), as.Date('2014-01-10'), by = 1), 
       type =c('return', 'order', 'order', 'return', 'order', 'order', 'return', 'return', 'order', 'order'), 
       qty = c(1, -1, -1, 1, -1, -1, 1, 1, -1, -1)) 
df 
    item  date type qty 
1  a 2014-01-01 return 1 
2  a 2014-01-02 order -1 
3  a 2014-01-03 order -1 
4  a 2014-01-04 return 1 
5  a 2014-01-05 order -1 
6  a 2014-01-06 order -1 
7  a 2014-01-07 return 1 
8  a 2014-01-08 return 1 
9  a 2014-01-09 order -1 
10 a 2014-01-10 order -1 

İstenen çıkış:

order_notes işleme kolonu gerekli değildir.

item  date type qty on_hand fulfilled   order_notes 
1  a 2014-01-01 return 1  1   0     <NA> 
2  a 2014-01-02 order -1  0   1    fulfilled 
3  a 2014-01-03 order -1  0   0 rejected, out of stock 
4  a 2014-01-04 return 1  1   0     <NA> 
5  a 2014-01-05 order -1  0   1    fulfilled 
6  a 2014-01-06 order -1  0   0 rejected, out of stock 
7  a 2014-01-07 return 1  1   0     <NA> 
8  a 2014-01-08 return 1  2   0     <NA> 
9  a 2014-01-09 order -1  1   1    fulfilled 
10 a 2014-01-10 order -1  0   1    fulfilled 
+0

cevap için teşekkür ederiz. – jwenzeslaus

cevap

2

İşte Atlanan numaralarını dengelemek için negatif bir asgari mutlak değerini ekleyerek, sıfırdan cumsum oluşturur bir seçenek. Gönderen

df %>% mutate(
    on_hand = sapply(seq_along(qty), function(x){ # loop over indices of qty 
     # sum to index and add the absolute value of the minimum of the cumsum and 0, i.e. 
     # the number of unfulfilled orders so far 
     sum(df$qty[1:x]) + abs(min(0, cumsum(df$qty)[1:x]))}), 

    # if type is return or on_hand doesn't change, 0, else 1 
    fulfilled = ifelse(type == 'return' | on_hand == lag(on_hand), 0, 1), 

    # if type is return, NA, else fulfilled/rejected... for fulfilled == 1 and 0 
    order_notes = ifelse(type == 'return', NA_character_, 
         ifelse(fulfilled == 1, 'fulfilled', 'rejected, out of stock'))) 

# item  date type qty on_hand fulfilled   order_notes 
# 1  a 2014-01-01 return 1  1   0     <NA> 
# 2  a 2014-01-02 order -1  0   1    fulfilled 
# 3  a 2014-01-03 order -1  0   0 rejected, out of stock 
# 4  a 2014-01-04 return 1  1   0     <NA> 
# 5  a 2014-01-05 order -1  0   1    fulfilled 
# 6  a 2014-01-06 order -1  0   0 rejected, out of stock 
# 7  a 2014-01-07 return 1  1   0     <NA> 
# 8  a 2014-01-08 return 1  2   0     <NA> 
# 9  a 2014-01-09 order -1  1   1    fulfilled 
# 10 a 2014-01-10 order -1  0   1    fulfilled 
1

: Bounded cumulative sum?

cumsumBounded.cpp: 
#include <Rcpp.h> 
using namespace Rcpp; 
// [[Rcpp::export]]                
NumericVector cumsumBounded(NumericVector x, double low, double high) { 
    NumericVector res(x.size()); 
    double acc = 0; 
    for (int i=0; i < x.size(); ++i) { 
    acc += x[i]; 
    if (acc < low) acc = low; 
    else if (acc > high) acc = high; 
    res[i] = acc; 
    } 
    return res; 
} 
library(Rcpp) 
sourceCpp(file="cumsumBounded.cpp") 

df %>% 
group_by(sku) %>% 
arrange(dt) %>% 
mutate(on_hand = cumsumBounded(qty, low = 0, high = 1000), 
     fulfilled = ifelse(type == 'return' | cum_qty == lag(cum_qty, default = 0), 0, 1)) 
+0

"Sapply" dan biraz daha hızlı. – jwenzeslaus