编辑 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
我想得到以下信息:一个汇总列表,它计算用户列表中每个用户的事件数据中每个事件类型的数量。但是,只有当用户列表中的“CreatedDate”早于或等于事件数据中的“Date”时,才应计算事件。
所以对于上述数据,我最终想要得到:
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
到目前为止我是如何做到的我已经能够通过首先创建一个“dt.master”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
}
问题 这确实有效......但是我正在处理 9+ 百万个事件、250k+ 个用户、150+ 个事件类型。因此,上面的 while 循环在处理之前需要 HOURS。我用一小批 500 名用户对其进行了测试,其处理时间如下:
user system elapsed
179.33 62.92 242.60
我还在等待整批处理哈哈。我在某处读到应该避免循环,因为它们需要很多时间。然而,我对 R 和编程完全陌生,我一直在通过反复试验和谷歌搜索来学习我需要的任何东西。显然,这会导致一些困惑的代码。我想知道是否有人可以指出我可能更快/更有效的方向?谢谢!
编辑:刚刚计算了一下,以我目前的方式完成它可能需要大约 37 个小时,所以如果有人有任何提示可以加快速度。请告诉我 :)
TL,博士:我的事件聚合/汇总代码需要几个小时来处理我的数据(它还没有完成)。有没有更快的方法来做到这一点?
最佳答案
假设您的数据已经在 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
回应评论和更新的问题:您可以通过在
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
关于r - 创建用户事件数据的汇总表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42160847/