【问题标题】:Extracting event types from last 21 day window从过去 21 天窗口中提取事件类型
【发布时间】:2015-05-25 18:09:48
【问题描述】:

我的数据框看起来像这样。最右边的两列是我想要的列。

**Name      ActivityType     ActivityDate   Email(last 21 says)  Webinar(last21)**             
John       Email            1/1/2014        NA                   NA   
John       Webinar          1/5/2014        NA                   NA
John       Sale             1/20/2014       Yes                  Yes
John       Webinar          3/25/2014       NA                   NA
John       Sale             4/1/2014        No                   Yes
John       Sale             7/1/2014        No                   No
Tom        Email            1/1/2015        NA                   NA   
Tom        Webinar          1/5/2015        NA                   NA
Tom        Sale             1/20/2015       Yes                  Yes
Tom        Webinar          3/25/2015       NA                   NA
Tom        Sale              4/1/2015        No                   Yes
Tom        Sale              7/1/2015        No                   No                

我只是想创建一个是/否变量来表示在过去 21 天内是否有针对每个“销售”交易的电子邮件或网络研讨会。我在想(模拟代码)以这种方式使用 dplyr:

custlife %>% 
group_by(Name) %>% 
 mutate(Email(last21days)=lag(ifelse(ActivityType = "Email" & ActivityDate of email within (activity date of sale - 21),Yes,No)).

我不确定实现这一点的方法。请帮忙。衷心感谢您的帮助!

【问题讨论】:

  • 如果你有一整天的时间,例如 2014 年 1 月 1 日、2014 年 2 月 1 日、2014 年 3 月 1 日……那么你可以在 cumsum(Email)lag(x, k = 21) 上工作。顺便说一句,在上述问题的上下文中,可以跳过 NA 电子邮件行。其他低效的方法是生成一组日期,其中之前的电子邮件不超过 21 天或同一天。然后加入原始集合。
  • 为什么Webinar 行也有“yes”,你不是只检查Sale 行吗?
  • @DavidArenburg 你是对的。我在制作示例时犯了一个错误。感谢您指出这一点。
  • 数据在哪里??
  • @jangorecki 你是什么意思?数据在问题中

标签: r dplyr zoo


【解决方案1】:

这是一个可能的data.table 解决方案。在这里,我创建了 2 个临时数据集 - 一个用于 Sale,一个用于其他活动类型,然后在使用 by = .EACHI 的同时通过 21 个滚动窗口将它们连接起来,以检查每个连接中的条件。然后,我将结果加入原始数据集。

将日期列转换为Date 类并按名称和日期键入数据(用于最终/滚动连接)

library(data.table)
setkey(setDT(df)[, ActivityDate := as.IDate(ActivityDate, "%m/%d/%Y")], Name, ActivityDate)

为每个活动创建 2 个临时数据集

Saletemp <- df[ActivityType == "Sale", .(Name, ActivityDate)]
Elsetemp <- df[ActivityType != "Sale", .(Name, ActivityDate, ActivityType)]

在检查条件时通过 21 的滚动窗口加入到销售临时数据集

Saletemp[Elsetemp, `:=`(Email21 = as.logical(which(i.ActivityType == "Email")), 
                        Webinar21 = as.logical(which(i.ActivityType == "Webinar"))), 
         roll = -21, by = .EACHI]

加入一切

df[Saletemp, `:=`(Email21 = i.Email21, Webinar21 = i.Webinar21)]
df
#     Name ActivityType ActivityDate Email21 Webinar21
#  1: John        Email   2014-01-01      NA        NA
#  2: John      Webinar   2014-01-05      NA        NA
#  3: John         Sale   2014-01-20    TRUE      TRUE
#  4: John      Webinar   2014-03-25      NA        NA
#  5: John         Sale   2014-04-01      NA      TRUE
#  6: John         Sale   2014-07-01      NA        NA
#  7:  Tom        Email   2015-01-01      NA        NA
#  8:  Tom      Webinar   2015-01-05      NA        NA
#  9:  Tom         Sale   2015-01-20    TRUE      TRUE
# 10:  Tom      Webinar   2015-03-25      NA        NA
# 11:  Tom         Sale   2015-04-01      NA      TRUE
# 12:  Tom         Sale   2015-07-01      NA        NA

【讨论】:

  • 非常感谢大卫!衷心感谢您的帮助。
【解决方案2】:

这是base R 的另一个选项:

df 首先根据Name 拆分,然后在每个子集中,对于每个Sale,它会查看销售后 21 天内是否有电子邮件(网络研讨会)。最后,列表根据Name进行unsplit。
之后您只需将FALSE 替换为noTRUE 替换为yes

df_split <- split(df, df$Name)

df_split <- lapply(df_split, function(tab){
                                i_s <- which(tab[,2]=="Sale")
                                tab$Email21[i_s] <- sapply(tab[i_s, 3], function(d_s){any(tab[tab$ActivityType=="Email", 3] >= d_s-21)})
                                tab$Webinar21[i_s] <- sapply(tab[i_s, 3], function(d_s){any(tab[tab$ActivityType=="Webinar", 3] >= d_s-21)})
                                tab
                              })
df_res <- unsplit(df_split, df$Name)

df_res
#   Name ActivityType ActivityDate Email21 Webinar21
#1  John        Email   2014-01-01      NA        NA
#2  John      Webinar   2014-01-05      NA        NA
#3  John         Sale   2014-01-20    TRUE      TRUE
#4  John      Webinar   2014-03-25      NA        NA
#5  John         Sale   2014-04-01   FALSE      TRUE
#6  John         Sale   2014-07-01   FALSE     FALSE
#7   Tom        Email   2015-01-01      NA        NA
#8   Tom      Webinar   2015-01-05      NA        NA
#9   Tom         Sale   2015-01-20    TRUE      TRUE
#10  Tom      Webinar   2015-03-25      NA        NA
#11  Tom         Sale   2015-04-01   FALSE      TRUE
#12  Tom         Sale   2015-07-01   FALSE     FALSE

数据

df <- structure(list(Name = c("John", "John", "John", "John", "John", 
"John", "Tom", "Tom", "Tom", "Tom", "Tom", "Tom"), ActivityType = c("Email", 
"Webinar", "Sale", "Webinar", "Sale", "Sale", "Email", "Webinar", 
"Sale", "Webinar", "Sale", "Sale"), ActivityDate = structure(c(16071, 
16075, 16090, 16154, 16161, 16252, 16436, 16440, 16455, 16519, 
16526, 16617), class = "Date")), .Names = c("Name", "ActivityType", 
"ActivityDate"), row.names = c(NA, -12L), index = structure(integer(0), ActivityType = c(1L, 
7L, 3L, 5L, 6L, 9L, 11L, 12L, 2L, 4L, 8L, 10L)), class = "data.frame")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多