跟踪R中的滞后属性

时间:2018-10-25 09:22:09

标签: r dplyr

我试图跟踪特定属性在列中的最后一个实例,但似乎无法为我工作。例如,如果我有一个交易数据库,我想保留购买的特定项目子集(在本例中为Drill)中最后一个的运行标志,以便:

Transactions <- data.table(Customer=c("A01","A01","A01","A01","A01","A01"), 
                           PurchaseDate=c("1/1/2018","1/2/2018","1/3/2018","1/4/2018","1/5/2018","1/6/2018"),
                           Purchase=c("DrillA, Bit10", "Bit11","Bit20","Bit21","DrillZ, Bit4", "Bit6"))

成为:

Transactions <- data.table(Customer=c("A01","A01","A01","A01","A01","A01"), 
                           PurchaseDate=c("1/1/2018","1/2/2018","1/3/2018","1/4/2018","1/5/2018","1/6/2018"),
                           Purchase=c("DrillA, Bit10", "Bit11","Bit20","Bit21","DrillZ, Bit4", "Bit6"), 
                           LastDrill=c("DrillA","DrillA","DrillA", "DrillA", "DrillZ", "DrillZ"))

我原本以为我可以用case_when处理这个,但是我看不到过去的那一行:

Transactions %>% 
  arrange(Customer, PurchaseDate) %>%
  group_by(Customer) %>%
  mutate(LastDrill = "") %>%
  mutate(LastDrill = case_when(grepl("DrillA", Purchase) ~ "DrillA",
                               grepl("DrillZ", Purchase) ~ "DrillZ",
                               TRUE ~ lag(LastDrill, 1, order_by=PurchaseDate)))

这似乎适用于紧随包含“ DrillA / DrillZ”的事务之后的事务,但是并不能保持“ flag”的进行。

是否有更好的方法来构造它?任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

数据

Transactions <- data.frame(Customer=c("A01","A01","A01","A01","A01","A01"), 
                           PurchaseDate=c("1/1/2018","1/2/2018","1/3/2018","1/4/2018","1/5/2018","1/6/2018"),
                           Purchase=c("DrillA, Bit10", "Bit11","Bit20","Bit21","DrillZ, Bit4", "Bit6"))

选项1 (tidyverse和重塑)

library(tidyverse)

Transactions %>% 
  arrange(Customer, PurchaseDate) %>%
  group_by(Customer) %>%
  separate_rows(Purchase) %>%                          # separate column into multiple rows (i.e. one event per row)
  mutate(flag = cumsum(grepl("Drill", Purchase))) %>%  # group rows based on when drills occur
  group_by(flag, add = T) %>%                          
  mutate(LastDrill = first(Purchase)) %>%              # get the first value in a new column (should always be a drill)
  ungroup() %>%
  select(-flag) %>%
  group_by(Customer, PurchaseDate, LastDrill) %>%
  summarise(Purchase = paste0(Purchase, collapse = ", ")) %>% # go back to your original shape
  ungroup()

#   Customer PurchaseDate      Purchase LastDrill
# 1      A01     1/1/2018 DrillA, Bit10    DrillA
# 2      A01     1/2/2018         Bit11    DrillA
# 3      A01     1/3/2018         Bit20    DrillA
# 4      A01     1/4/2018         Bit21    DrillA
# 5      A01     1/5/2018  DrillZ, Bit4    DrillZ
# 6      A01     1/6/2018          Bit6    DrillZ

选项2 (dplyr和提取练习的功能)

library(dplyr)
library(zoo)

# vectorised function to extract the drill value from a string
# (uses comma to split the string)
GetDrill = function(x) { y = unlist(strsplit(x, split = ","))
                         ifelse(sum(grepl("Drill", y)), y[grepl("Drill", y)], NA) }
GetDrill = Vectorize(GetDrill)


Transactions %>% 
  arrange(Customer, PurchaseDate) %>%
  group_by(Customer) %>%
  mutate(LastDrill =  na.locf(GetDrill(as.character(Purchase)))) %>%
  ungroup()

# # A tibble: 6 x 4
#   Customer PurchaseDate Purchase      LastDrill
#   <fct>    <fct>        <fct>         <chr>    
# 1 A01      1/1/2018     DrillA, Bit10 DrillA   
# 2 A01      1/2/2018     Bit11         DrillA   
# 3 A01      1/3/2018     Bit20         DrillA   
# 4 A01      1/4/2018     Bit21         DrillA   
# 5 A01      1/5/2018     DrillZ, Bit4  DrillZ   
# 6 A01      1/6/2018     Bit6          DrillZ