如何根据日期计算频率

时间:2017-01-06 13:57:55

标签: r date count frequency

我想知道是否有人可以帮我解决以下问题:

我有两个数据集: (1)一个包含id和order_date (2)第二个包含相同的id和delivery_dates的电子邮件

我想计算一个人在order_date之前收到的电子邮件数量。但是,我无法做到这一点。当我合并两个数据文件时,order_dates与交付日期相结合,这不是我想要的。此外,我不想计算一个人的所有交付日期,因为它需要依赖于时间。

我希望有人可以帮助我!!

示例数据集1:

id.  order_date age
xx3  2014/07/04 72
xx3  2014/10/08 72
xx3  2014/11/12 72
xx7  2014/05/02 34
xx7  2014/07/09 34
xx9  2014/12/22 55

示例数据集2:

id. delivery_date 
xx3 2014/07/02
xx3 2014/08/10
xx3 2014/11/02
xx3 2014/07/02
xx3 2014/12/02
xx3 2014/12/11
xx7 2014/07/05

我想要的是什么:

id. frequency_received order_date
xx3 1                  2014/07/04
xx3 3                  2014/10/08

日期为YYYYMMDD格式。

2 个答案:

答案 0 :(得分:2)

有条件合并尚未在dplyr中实施,您可以使用data.table,也可以使用sqldf,如下所示:

library(sqldf)
library(lubridate)
library(dplyr)

options(sqldf.driver = "SQLite")

tblA <- data.frame(id = c('xx3', 'xx3', 'xx3', 'xx7', 'xx7', 'xx9'),
                   order_date = c('2014/07/04', '2014/10/08', '2014/11/12',
                                  '2014/05/02', '2014/07/09', '2014/12/22'),
                   age = c(72, 72, 72, 34, 34, 55),
                   stringsAsFactors = FALSE)

tblB <- data.frame(id = c('xx3', 'xx3', 'xx3', 'xx3', 'xx3', 'xx3', 'xx7'),
                   delivery_date = c('2014/07/02', '2014/08/10', '2014/11/02',
                                     '2014/07/02', '2014/12/02', '2014/1211',
                                     '2014/07/05'),
                   stringsAsFactors = FALSE)

tblA$order_date <- ymd(tblA$order_date)
tblB$delivery_date <- ymd(tblB$delivery_date)

tblC <- sqldf("select tblA.id, order_date, delivery_date
               from tblA
               join tblB
                 on tblA.id = tblB.id
                 and tblA.order_date >= tblB.delivery_date")

tblC
answer <- tblC %>%
    group_by(id, order_date) %>%
    summarise(frequency_received = n())

as.data.frame(answer)

这给出了:

   id order_date frequency_received
1 xx3 2014-07-04                  2
2 xx3 2014-10-08                  3
3 xx3 2014-11-12                  4
4 xx7 2014-07-09                  1

答案 1 :(得分:1)

一种可能的解决方案是使用foverlaps中的data.table - 函数 - 包:

library(data.table)
# convert the 'data.frame's to 'data.table's with setDT()
setDT(ds1)
setDT(ds2)

# create a reference dataset with the minimum dates for each id
md <- ds2[, min(delivery_date), id
          ][ds1[, min(order_date), id], on = 'id'
            ][is.na(V1), V1 := i.V1
              ][, mindate := pmin(V1, i.V1)
                ][, .(id, mindate)]

# create a start date for the time window in which the emails should have been sent
ds1[, bdate := shift(order_date, fill = min(md$mindate[match(id,md$id)])-1), by = id]
# create 2nd deliverydate needed for the foverlaps function
ds2[, delivery_date2 := delivery_date]

# set the keys for each 'data.table'
setkey(ds1, id, bdate, order_date)
setkey(ds2, id, delivery_date, delivery_date2)

# perform the overlap join & calculate the number of recieved emails (freq)
foverlaps(ds1, ds2, nomatch = 0)[, .(freq = .N), by = .(id, order_date)][, freq := cumsum(freq), by = id][]

给出:

    id order_date freq
1: xx3 2014-07-04    2
2: xx3 2014-10-08    3
3: xx3 2014-11-12    4
4: xx7 2014-07-09    1

使用过的数据:

ds1 <- structure(list(id = structure(c(1L, 1L, 1L, 2L, 2L, 3L), .Label = c("xx3", "xx7", "xx9"), class = "factor"), 
                      order_date = structure(c(16255, 16351, 16386, 16192, 16260, 16426), class = "Date"), 
                      age = c(72L, 72L, 72L, 34L, 34L, 55L)), 
                 .Names = c("id", "order_date", "age"), row.names = c(NA, -6L), class = "data.frame")
ds2 <- structure(list(id = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L), .Label = c("xx3", "xx7"), class = "factor"), 
                      delivery_date = structure(c(16253, 16292, 16376, 16253, 16406, 16415, 16256), class = "Date")), 
                 .Names = c("id", "delivery_date"), row.names = c(NA, -7L), class = "data.frame")
相关问题