当前位置: 首页 > 面试题库 >

R的滚动日期范围内的唯一值计数

贲宏硕
2023-03-14
问题内容

这个问题已经有了SQL的答案,并且我能够使用R在R中实现该解决方案sqldf。但是,我一直找不到使用来实现它的方法data.table

问题是要计算滚动日期范围内一列的不同值,例如(如果直接从链接的问题中引用)数据是否如下所示:

Date   | email 
-------+----------------
1/1/12 | test@test.com
1/1/12 | test1@test.com
1/1/12 | test2@test.com
1/2/12 | test1@test.com
1/2/12 | test2@test.com
1/3/12 | test@test.com
1/4/12 | test@test.com
1/5/12 | test@test.com
1/5/12 | test@test.com
1/6/12 | test@test.com
1/6/12 | test@test.com
1/6/12 | test1@test.com

如果我们使用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在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('test@test.com', 'test1@test.com','test2@test.com',
           'test1@test.com', 'test2@test.com','test@test.com',
           'test@test.com','test@test.com','test@test.com',
           'test@test.com','test@test.com','test1@test.com')
dt <- data.table(date, email)

在这方面的任何帮助将不胜感激。谢谢!

编辑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;

编辑2:这是根据@jangorecki要求的基于@MichaelChirico解决方案的一些时间安排:

# 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

输出是等效的,但是使用data.table而不是sqldf导致速度提高了12.5倍。相当可观!


问题答案:

利用的新的非等额连接功能,这是可行的方法data.table

dt[dt[ , .(date3=date, date2 = date - 2, email)], 
   on = .(date >= date2, date<=date3), 
   allow.cartesian = TRUE
   ][ , .(count = uniqueN(email)), 
      by = .(date = date + 2)]
#          date V1
# 1: 2011-12-30  3
# 2: 2011-12-31  3
# 3: 2012-01-01  3
# 4: 2012-01-02  3
# 5: 2012-01-03  1
# 6: 2012-01-04  2

老实说,我对它的工作方式有点不满意,但是我的想法是加入dt进来date,匹配date两天前到今天之间的任何东西。我不确定为什么我们必须在date = date + 2事后进行清理。

这是一种使用键的方法:

setkey(dt, date)

dt[ , .(count = dt[.(seq.Date(.BY$date - 2L, .BY$date, "day")),
                   uniqueN(email), nomatch = 0L]), by = date]


 类似资料:
  • 问题内容: 我有一组电子邮件地址和将这些电子邮件地址添加到表中的日期的数据集。电子邮件地址在不同的日期可以有多个条目。例如,如果我有下面的数据集。我希望获得上述日期和3天前之间不同电子邮件的日期和计数。 如果我们使用3的日期周期,结果集将看起来像这样 我可以使用下面的查询来获得日期范围的不同计数,但希望按天获得一个范围的计数,因此我不必手动更新数百个日期的范围。 感谢您的帮助。 问题答案: 测试用

  • 我想获得一个每月平均值,该平均值仅计算包含交易的月份。这就像将所有交易金额相加,然后除以使用的月数一样简单。 我找不到一个本机Excel公式可以像这样计算月份,并且尝试使用表或命名范围对基于ROW()函数的条件求和不起作用。它只会在尝试按年(或任何其他条件)限制计数时返回零。 该公式如下所示: 顺便说一句,这是一个数组公式。它基本上会查看您所在的行是否与排序列表中引用月份的第一行相同。这是我尝试过

  • 问题内容: 我的数据库中有以下一组匹配日期的日期(dd / MM / yyyy): 事件具有开始和结束日期(时间无关紧要),并且endDate为NULL表示事件仍在进行中。 我想确定的是两个任意日期之间的日期范围,其中a)没有事件,b)事件重叠。 因此,对于输入日期范围01/04/2009-30/06/2009,我希望得到以下结果: 注意,作为结果,两个相邻的重叠范围是可以接受的。 谁能用SQL算

  • 我面临着许多困难。 1)虽然在演讲和历史数据中都有日期信息,但在第一个数据中,我有每个条目的具体日期,在第二个数据中有一个日期范围。理想情况下,我希望能够合并,以便每个演讲条目都与演讲者(姓名)和演讲日期所属的历史条目匹配。 2)期望的输出是有一个data.frame或data.table,其行等于演讲data.frame中的观察值,以及名称、日期和每个角色的列(它们将由值填充)。然而,某些角色在

  • 问题内容: 这比看起来难。我需要一个函数来计算日期范围内给定工作日的数量。我不需要任何循环或递归SQL。数以百万计的示例就是这样做的。我需要一个快速函数来进行计算。 该函数的输入将是工作日,fromdata,迄今为止 预期结果: 问题答案: @Mikael Eriksson有一个绝妙的主意,但是他的实现似乎有些复杂。 这是我想出的(我想强调一下, 它基于 @Mikael 的 解决方案 ,主要功劳应

  • 问题内容: 我的MySQL表包含以下列:datetime,price_paid。我正在尝试计算一周中每天两次(两次约会之间)的平均销售额。这意味着我需要在startDate和endDate日期之间选择销售总和,并按工作日分组,然后将其除以该范围内每个工作日发生的次数。 我得到了第一部分: 我没有的是缺少的价值:我应该除以的数量-每天出现在该范围内的次数。我尝试了几种解决方案,但无济于事。 有人可以