2017-02-10 12 views
4

Редактирование 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  [email protected]*.com Type2  2016-01-02 
User1  [email protected]*.com Type6  2016-01-02 
User1  [email protected]*.com Type1  2016-01-02 
User1  [email protected]*.com Type3  2016-01-02 
User2  [email protected]*.com Type1  2016-01-02 
User2  [email protected]*.com Type1  2016-01-02 
User2  [email protected]*.com Type2  2016-01-02 
User3  [email protected]*.com Type1  2016-01-02 
User3  [email protected]*.com Type3  2016-01-02 
User1  [email protected]*.com Type2  2016-01-04 
User1  [email protected]*.com Type2  2016-01-04 
User2  [email protected]*.com Type5  2016-01-04 
User3  [email protected]*.com Type1  2016-01-04 
User3  [email protected]*.com Type4  2016-01-04 

Каждый раз, когда пользователь делает что-то, событие записываются с типом события, с отметкой времени.

список пользователей из различных баз данных:

UserID Email   CreatedDate 

DxUs1  [email protected]*.com 2016-01-01 
DxUs2  [email protected]*.com 2016-01-03 
DxUs3  [email protected]*.com 2016-01-03 

Я хочу, чтобы получить следующее:

, сокращенного список, который подсчитывает количество каждого типа события в данных событиях для каждого пользователя в Список пользователей. Однако события должны учитываться только в том случае, если «Созданная дата» в списке пользователей до или равна «Дате» в данных события.

Таким образом, для приведенных выше данных, я бы в конечном итоге хотите получить:

Email   Type1 Type2 Type3 Type4  Type5  Type6 
[email protected]*.com 1  3  1  0   0   1 
[email protected]*.com 0  0  1  0   1   0 
[email protected]*.com 1  0  0  1   0   0 

Как мне удалось сделать это до сих пор

Я был в состоянии сделать это сначала создать таблицу данных dt.master, включающую все столбцы для всех событий и список писем. Который выглядит следующим образом:

Email   Type1 Type2 Type3 Type4  Type5  Type6 
[email protected]*.com 0  0  0  0   0   0 
[email protected]*.com 0  0  0  0   0   0 
[email protected]*.com 0  0  0  0   0   0 

А затем заполнить эту таблицу, используя время цикла ниже:

# 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+ типов событий. Поэтому вышеописанный цикл принимает HOURS до его обработки.Я проверил это с небольшой партией 500 пользователей, которые имели следующее время обработки:

user system elapsed 
179.33 62.92  242.60 

Я все еще в ожидании полной партии, чтобы быть обработаны ха-ха. Я где-то читал, что следует избегать циклов, поскольку они занимают много времени. Однако я совершенно новичок в R и программировании в целом, и я изучаю пробную версию/ошибку и Googling независимо от того, что мне нужно. Очевидно, что это приводит к некорректному коду. Мне было интересно, может ли кто-нибудь указать мне в сторону чего-то, что может быть быстрее/эффективнее?

Спасибо!

Редактировать: Просто рассчитано, что, вероятно, потребуется около 37 часов, чтобы завершить то, как я это делаю сейчас, поэтому, если у кого есть какие-либо советы, чтобы сделать это быстрее. Пожалуйста, дайте мне знать :)

TL, DR: Мое сообщение об агрегировании/суммировании событий занимает несколько часов, чтобы обработать мои данные (это еще не сделано). Есть ли более быстрый способ сделать это?

+0

вы должны проверить длинный/широкий format - '? reshape()' – BigDataScientist

+0

Я откат назад, поскольку решения принадлежат к ответам, надеюсь, что вы не против – Jaap

+0

Кроме того: поздравляю с первым вопросом на SO! Хорошо сформулированный и, следовательно, пример для всех новых пользователей imo. – Jaap

ответ

3

Если предположить, что данные уже в data.table, вы можете использовать параметр fun.aggregate в dcast:

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

дает:

  Email Type1 Type2 Type3 Type4 Type5 Type6 
1: [email protected]*.com  1  2  1  0  0  1 
2: [email protected]*.com  4  1  0  0  1  0 
3: [email protected]*.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: [email protected]*.com  1  2  1  0  0  1 
2: [email protected]*.com  1  0  0  0  1  0 
3: [email protected]*.com  0  1  0  1  0  0 
+0

Это то, что я искал. Спасибо! Однако мне все же необходимо убедиться, что вы не включили/не засчитали все события, а только те, которые были до даты в другой таблице. Я вижу, что у dcast есть аргумент подмножества, я попытаюсь использовать это! – Mark

+0

Hi Jaap, Я пытаюсь использовать dcast, но также и подмножество, используя другую таблицу данных. Я попытался: 'dcast (dt.events, Email ~ EventType, fun.aggregate = length, subset = as.Date (Date) <= as.Date (dt.users $ CreatedDate [dt.users $ Email = dt .events $ Email])) ' Это, однако, дает мне ошибку: ' Ошибка, в которой (eval (subset, data, parent.frame())): аргумент для «который» не является логическим I предположим, потому что логика подмножества неверна. Есть ли другой способ его подмножества, или я должен сначала добавить CreateDate в dt.events и использовать его для подмножества? – Mark

+0

@Mark см. Обновление моего ответа – Jaap

2

непроверенных

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

 Смежные вопросы

  • Нет связанных вопросов^_^