У этого вопроса уже есть answer for SQL, и я смог реализовать это решение в R, используя sqldf
. Однако мне не удалось найти способ реализовать его, используя data.table
.Количество уникальных значений в диапазоне дат прокатки для R
Задача состоит в том, чтобы подсчитать отдельные значения одного столбца в пределах диапазона дат прокатки, например. (И цитирование непосредственно из связанного вопроса), если данные выглядели так:
Date | email
-------+----------------
1/1/12 | [email protected]
1/1/12 | [email protected]
1/1/12 | [email protected]
1/2/12 | [email protected]
1/2/12 | [email protected]
1/3/12 | [email protected]
1/4/12 | [email protected]
1/5/12 | [email protected]
1/5/12 | [email protected]
1/6/12 | [email protected]
1/6/12 | [email protected]
1/6/12 | [email protected]
Тогда множество результат будет выглядеть примерно так, если мы использовали период дат 3 дня
date | count(distinct email)
-------+------
1/1/12 | 3
1/2/12 | 3
1/3/12 | 3
1/4/12 | 3
1/5/12 | 2
1/6/12 | 2
Вот код для создания тех же данных в R с помощью data.table
:
date <- as.Date(c('2012-01-01','2012-01-01','2012-01-01',
'2012-01-02','2012-01-02','2012-01-03',
'2012-01-04','2012-01-05','2012-01-05',
'2012-01-06','2012-01-06','2012-01-06'))
email <- c('[email protected]', '[email protected]','[email protected]',
'[email protected]', '[email protected]','[email protected]',
'[email protected]','[email protected]','[email protected]',
'[email protected]','[email protected]','[email protected]')
dt <- data.table(date, email)
Любая помощь по этому вопросу будет высоко ценится. Благодаря!
Edit 1:
Это проблема игрушки, которую я хочу, чтобы применить к гораздо большему набору данных, поэтому использование декартовых произведений является проблематичным. Вместо этого я хотел бы что-то, что эквивалентно коррелированному подзапросу в SQL, например. решение от вопроса, который я изначально связан был:
SELECT day
,(SELECT count(DISTINCT email)
FROM tbl
WHERE day BETWEEN t.day - 2 AND t.day -- period of 3 days
) AS dist_emails
FROM tbl t
WHERE day BETWEEN '2012-01-01' AND '2012-01-06'
GROUP BY 1
ORDER BY 1;
Edit 2: Вот некоторые сроки на основе @ решение MichaelChirico, в соответствии с просьбой @jangorecki:
# The data
> dim(temp)
[1] 2627785 4
> head(temp)
date category1 category2 itemId
1: 2013-11-08 0 2 1713
2: 2013-11-08 0 2 90485
3: 2013-11-08 0 2 74249
4: 2013-11-08 0 2 2592
5: 2013-11-08 0 2 2592
6: 2013-11-08 0 2 765
> uniqueN(temp$itemId)
[1] 13510
> uniqueN(temp$date)
[1] 127
# Timing for data.table
> system.time(dtTime <- temp[,
+ .(count = temp[.(seq.Date(.BY$date - 6L, .BY$date, "day"),
+ .BY$category1, .BY$category2), uniqueN(itemId), nomatch = 0L]),
+ by = c("date","category1","category2")])
user system elapsed
6.913 0.130 6.940
>
# Time for sqldf
> system.time(sqlDfTime <-
+ sqldf(c("create index ldx on temp(date, category1, category2)",
+ "SELECT date, category1, category2,
+ (SELECT count(DISTINCT itemId)
+ FROM temp
+ WHERE category1 = t.category1 AND category2 = t.category2 AND
+ date BETWEEN t.date - 6 AND t.date
+ ) AS numItems
+ FROM temp t
+ GROUP BY date, category1, category2
+ ORDER BY 1;"))
user system elapsed
87.225 0.098 87.295
Выходы eqivalent, но использование data.table, а не sqldf привело к ускорению 12.5x. Довольно существенный!
Привет, могли бы вы пожалуйста, объясните отчетный счет электронной почты, таким образом он сможет помочь. Спасибо. –
Я думаю, что 1/5/12 должно иметь счет = 2. – MichaelChirico
Если вы хотите только ежедневное количество уникальных писем, как насчет 'dt [, length (unique (email)), by = date]'? –