创建用户事件数据的汇总表

时间:2017-02-10 13:43:02

标签: r sum data.table aggregation

编辑2:我意识到我可以使用dcast()来做我想做的事情。但是,我不想计算事件数据中的所有事件,只计算在另一个数据集中指定的日期之前发生的事件。我似乎无法弄清楚如何在dcast()中使用子集参数。到目前为止,我已经尝试过:

dcast(dt.events, Email ~ EventType, fun.aggregate = length, subset = as.Date(Date) <= 
as.Date(dt.users$CreatedDate[dt.users$Email = dt.events$Email]))

然而,这不起作用。我可以将CreatedDate中的dt.users列添加到dt.events。然后使用以下子集:

dcast(dt.events, Email ~ EventType, fun.aggregate = length, subset = as.Date(Date) <=
as.Date(CreatedDate)

我想知道是否可以在不添加额外列的情况下执行此操作?

编辑:刚刚计算出它可能需要大约37个小时才能完成我目前正在进行的工作,所以如果有人有任何提示可以让它更快。请让我知道:))

我是R的新手,我已经找到了一种方法来做我想做的事情。但效率极低,需要数小时才能完成。

我有以下内容:

活动数据:

UserID    Email         EventType    Date

User1     User1@*.com   Type2        2016-01-02
User1     User1@*.com   Type6        2016-01-02
User1     User1@*.com   Type1        2016-01-02
User1     User1@*.com   Type3        2016-01-02
User2     User2@*.com   Type1        2016-01-02
User2     User2@*.com   Type1        2016-01-02
User2     User2@*.com   Type2        2016-01-02
User3     User3@*.com   Type1        2016-01-02
User3     User3@*.com   Type3        2016-01-02
User1     User1@*.com   Type2        2016-01-04
User1     User1@*.com   Type2        2016-01-04
User2     User2@*.com   Type5        2016-01-04
User3     User3@*.com   Type1        2016-01-04
User3     User3@*.com   Type4        2016-01-04

每次用户执行某项操作时,都会使用带有时间戳的事件类型记录事件。

来自不同数据库的用户列表:

UserID    Email         CreatedDate

DxUs1     User1@*.com   2016-01-01
DxUs2     User2@*.com   2016-01-03
DxUs3     User3@*.com   2016-01-03

我想获得以下内容:

汇总列表,用于计算用户列表中每个用户的事件数据中每种事件类型的数量。但是,只有在&#34; CreatedDate&#34;在用户列表中等于&#34;日期&#34;在事件数据中。

因此,对于上述数据,我最终希望得到:

Email         Type1    Type2    Type3    Type4     Type5     Type6
User1@*.com   1        3        1        0         0         1
User2@*.com   0        0        1        0         1         0
User3@*.com   1        0        0        1         0         0

到目前为止我是如何设法的

我已经能够通过首先创建一个&#39; dt.master&#39; data.table,包括所有事件的所有列和电子邮件列表。看起来像这样:

Email         Type1    Type2    Type3    Type4     Type5     Type6
User1@*.com   0        0        0        0         0         0
User2@*.com   0        0        0        0         0         0
User3@*.com   0        0        0        0         0         0

然后使用下面的while循环填写此表:

# The data sets
dt.events # event data
dt.users # user list
dt.master # blank master table

# Loop that fills master table
counter_limit = group_size(dt.master)
index = 1

while (index <= counter_limit) {

    # Get events of user at current index
    dt.events.temp = filter(dt.events, dt.events$Email %in% dt.users$Email[index], 
                     as.Date(dt.events$Date) <= as.Date(dt.users$CreatedDate[index]))

    # Count all the different events
    dt.event.counter = as.data.table(t(as.data.table(table(dt.events.temp$EventType))))

    # Clean the counter by 1: Rename columns to event names, 2: Remove event names row
    names(dt.event.counter) = as.character(unlist(dt.event.counter[1,]))
    dt.event.counter = dt.event.counter[-1]

    # Fill the current index in on the blank master table
    set(dt.master, index, names(dt.event.counter), dt.event.counter)

    index = index + 1
}

问题

这确实有效......但我正在处理超过900万个事件,250k +用户,150多个事件类型。因此,上面的while循环在处理之前需要HOURS。我用一小批500个用户测试了它,它有以下处理时间:

user    system    elapsed
179.33  62.92     242.60

我还在等待整批处理哈哈。我已经读过应该避免循环的地方,因为它们需要花费很多时间。但是我对R和编程一般来说都是全新的,而且我一直在通过试用/错误和Google搜索来学习我需要的东西。显然,这会导致一些混乱的代码。我想知道是否有人能指出我可能更快/更有效的方向?

谢谢!

编辑:刚刚计算出它可能需要大约37个小时才能完成我目前正在进行的工作,所以如果有人有任何提示可以让它更快。请让我知道:))

TL,DR:我的事件聚合/汇总代码需要几个小时才能处理我的数据(它还没有完成)。有没有更快的方法呢?

2 个答案:

答案 0 :(得分:3)

假设您的数据已经在data.table,您可以使用fun.aggregate中的dcast参数:

dcast(dat, Email ~ EventType, fun.aggregate = length)

给出:

         Email Type1 Type2 Type3 Type4 Type5 Type6
1: User1@*.com     1     2     1     0     0     1
2: User2@*.com     4     1     0     0     1     0
3: User3@*.com     0     1     1     1     0     0

回应评论&amp;更新的问题:您可以通过在dcast - 函数中使用非等联接来获得所需的结果:

dcast(dt.events[dt.users, on = .(Email, Date >= CreatedDate)],
      Email ~ EventType, fun.aggregate = length)

给出:

         Email Type1 Type2 Type3 Type4 Type5 Type6
1: User1@*.com     1     2     1     0     0     1
2: User2@*.com     1     0     0     0     1     0
3: User3@*.com     0     1     0     1     0     0

答案 1 :(得分:2)

未测试

library(dpylr)
library(tidyr)
your.dataset %>%
  count(Email, EventType) %>%
  spread(EventType, n)