在特定条件下映射两个数据帧

时间:2016-08-05 00:39:38

标签: r

我已经问过this question

但是现在我目前的问题略有不同,我无法使用此解决方案或弄清楚。我想要数据集2之前发生的数据集中的数据,这是我的数据:

 # Dataset 1 (dts1)

     UserID   date   Hour     Events    
  1    5  25/07/2016  02:31      8         
  2    5  30/07/2016  02:42      6      
  3    4  23/07/2016  07:52      9         
  4   14  24/07/2016  03:02      5         
  5   17  25/07/2016  09:12      10        
  6    4  22/07/2016  03:22      4  

   # Dataset 2 (dts2)

    UserID       date   Hour      transactions     
 1     5    25/07/2016  02:29      4         
 2     4    24/07/2016  02:42      2       
 3     5    25/07/2016  02:52      3         
 4     6    24/07/2016  03:02      4         
 5     6    25/07/2016  03:12      1        
 6    14    26/07/2016  03:22      3  

所以,我希望比较数据集1中的那些数据集,并且只添加在数据集2之前发生的数据集。换句话说,我想确保我不计算在用户的最后一次交易之后发生的那些事件。理想输出如下:

    #output 

   UserID   Events      transaction 

    5         8         4,3
    4         9,4       2
   14         5         3
   17         10        NA

在上面的示例中,我确保删除了用户5的事件6,因为它发生在上一次交易之后。

2 个答案:

答案 0 :(得分:2)

我们首先将时间转换为POSIX类。

dts1$time <- strptime(paste(dts1$date, dts1$Hour), format="%d/%m/%Y %H:%M")
dts2$time <- strptime(paste(dts2$date, dts2$Hour), format="%d/%m/%Y %H:%M")

下一步是制作transactions列。我们首先按时间排序dts2(从最新到最早),然后使用by()函数将dts分组到UserID并从每个子集中取第一行。然后,我们使用tapply为每个transactions检索UserID

dts2 <- dts2[order(dts2$time, decreasing=TRUE), ]
out <- do.call(rbind, by(dts2[,c("UserID","time")], dts2$UserID, head, 1))
out$transactions <- tapply(dts2$transactions, dts2$UserID, c)

最后,我们使用您描述的规则构建Events列。

out$Events <- sapply(1:nrow(out), function(i) {
    User2 <- out$UserID[i]
    time2 <- out$time[i]
    rows <- which(dts1$UserID==User2 & dts1$time<time2)
    if (length(rows)>0) {            
        dts1$Events[rows]
    } else {
        NA
    }
})

结果:

> out
   UserID                time transactions Events
4       4 2016-07-24 02:42:00            2   9, 4
5       5 2016-07-25 02:52:00         3, 4      8
6       6 2016-07-25 03:12:00         1, 4     NA
14     14 2016-07-26 03:22:00            3      5

请注意,由于用户17不在dts2,因此它不会出现在out中。

答案 1 :(得分:2)

这是对上一个问题的@dimitris_ps答案的修改。如果他选择回答,我很乐意删除我的。

此问题与您之前的问题之间的主要区别在于,我们现在想要针对每个特定{{1}的最后 dts1交易之前的所有dts2个事件}。因此,我们首先要UserID group_by,然后UserID仅针对那些filter事件时间小于上一个dts1交易时间的行。然后我们dts2可以summariseEvents,仍然按transactions分组。

代码是:

UserID

结果是:

library(dplyr)

## I will not use the lubridate package, instead I will convert the time
## using as.POSIXct
dts1$time <- as.POSIXct(paste(dts1$date, dts1$Hour), format="%d/%m/%Y %H:%M")
dts2$time <- as.POSIXct(paste(dts2$date, dts2$Hour), format="%d/%m/%Y %H:%M")

# first join the two data.frames by UserID.
result <- left_join(dts1, dts2, by="UserID") %>%

# all subsequent processing is grouped by the UserID because we 
# want to compare the last transaction time to the Event times
# for each UserID.
group_by(UserID) %>%

# apply the filtering condition dts1 Event must be before last dts2 transaction.
# Note that we keep rows for which there is no row in  
# dts2 for a UserID in dts1. This is the case for UserID=17.
filter(is.na(time.y) | last(time.y) > time.x) %>% 

# summarise Events and transactions
summarise(Events = toString(unique(Events)), transactions = toString(unique(transactions)))

希望这有帮助。