R 合并按发件人分组的在同一时间范围内包含邮件的行

R 合并按发件人分组的在同一时间范围内包含邮件的行,r,time,group-by,merge,R,Time,Group By,Merge,我有一个数据框,其中包含来自whatsapp发件人的消息。通常,人们倾向于在whatsapp中使用不止一条消息来表达某件事。我的目标是将大约5分钟内发送的消息合并为一行。这必须按发件人分组,因为数据帧包含多个发件人。我的数据框看起来如下所示: Message Time Sender hello 2018-12-14 16:27:00 300 how are you? 2018-12-1

我有一个数据框,其中包含来自whatsapp发件人的消息。通常,人们倾向于在whatsapp中使用不止一条消息来表达某件事。我的目标是将大约5分钟内发送的消息合并为一行。这必须按发件人分组,因为数据帧包含多个发件人。我的数据框看起来如下所示:

Message             Time                    Sender
hello               2018-12-14 16:27:00     300
how are you?        2018-12-14 16:29:00     300
do you reply?       2018-12-15 12:00:00     300
Hi                  2018-12-14 16:30:00     200
Hi                  2018-12-15 16:36:00     200
现在我想让它看起来像这样:

Message             Time                    Sender
hello how are you?  2018-12-14 16:27:00     300
do you reply?       2018-12-15 12:00:00     300
Hi                  2018-12-14 16:30:00     200
Hi                  2018-12-15 16:3600      200
第一个和第二个已经合并。到目前为止,我的尝试是将组映射与reduce一起使用,但似乎找不到解决方案

joinedMessageTable <- messageTable %>% group_by(Sender) %>% group_map(function(table, sender) {
    Reduce(function(firstElement, result) {
        value <- (firstElement + 5 *60 > result)
    }, table$time)
})
joinedMessageTable%group\U by(发送方)%>%group\U映射(函数(表,发送方){
减少(函数(第一个元素,结果){
价值(结果)
},表$time)
})
有人知道如何解决这个问题吗?

这行得通吗:

library(stringr)
library(dplyr)
df %>% group_by(Sender) %>% 
   mutate(flag = +(difftime(lead(Time), Time, units = 'min') < 5), flag = replace_na(flag, 0),
          Message = case_when(flag == 1 ~ str_c(Message, lead(Message), sep = ' '), TRUE ~ Message),
          Time = case_when(lag(flag) == 1 & flag == 0 ~ lag(Time), TRUE ~ Time)) %>% select(-flag) %>% filter(!duplicated(Time))
# A tibble: 4 x 3
# Groups:   Sender [2]
  Message            Time                Sender
  <chr>              <dttm>               <dbl>
1 hello how are you? 2018-12-14 16:27:00    300
2 do you reply?      2018-12-15 12:00:00    300
3 Hi                 2018-12-14 16:30:00    200
4 Hi                 2018-12-15 16:36:00    200
库(stringr)
图书馆(dplyr)
df%%>%分组人(发件人)%%>%
变异(flag=+(difftime(超前(时间),时间,单位='min')<5),flag=replace_na(flag,0),
消息=case_当(标志==1~str_c(消息,引导(消息),sep=''),真消息),
时间=情况(滞后(标志)=1&标志==0~滞后(时间),真~时间))%>%select(-flag)%>%filter(!duplicated(时间))
#一个tibble:4x3
#分组:发件人[2]
消息时间发送器
你好,你好吗?2018-12-14 16:27:00    300
你回答了吗?2018-12-15 12:00:00    300
3嗨2018-12-14 16:30:00 200
4嗨2018-12-15 16:36:00 200
这是否有效:

library(stringr)
library(dplyr)
df %>% group_by(Sender) %>% 
   mutate(flag = +(difftime(lead(Time), Time, units = 'min') < 5), flag = replace_na(flag, 0),
          Message = case_when(flag == 1 ~ str_c(Message, lead(Message), sep = ' '), TRUE ~ Message),
          Time = case_when(lag(flag) == 1 & flag == 0 ~ lag(Time), TRUE ~ Time)) %>% select(-flag) %>% filter(!duplicated(Time))
# A tibble: 4 x 3
# Groups:   Sender [2]
  Message            Time                Sender
  <chr>              <dttm>               <dbl>
1 hello how are you? 2018-12-14 16:27:00    300
2 do you reply?      2018-12-15 12:00:00    300
3 Hi                 2018-12-14 16:30:00    200
4 Hi                 2018-12-15 16:36:00    200
库(stringr)
图书馆(dplyr)
df%%>%分组人(发件人)%%>%
变异(flag=+(difftime(超前(时间),时间,单位='min')<5),flag=replace_na(flag,0),
消息=case_当(标志==1~str_c(消息,引导(消息),sep=''),真消息),
时间=情况(滞后(标志)=1&标志==0~滞后(时间),真~时间))%>%select(-flag)%>%filter(!duplicated(时间))
#一个tibble:4x3
#分组:发件人[2]
消息时间发送器
你好,你好吗?2018-12-14 16:27:00    300
你回答了吗?2018-12-15 12:00:00    300
3嗨2018-12-14 16:30:00 200
4嗨2018-12-15 16:36:00 200

您可以使用
上限日期
创建每5分钟一组-

library(dplyr)
library(lubridate)

messageTable %>%
  group_by(Sender, Time = ceiling_date(mdy_hm(Time), unit = '5 mins')) %>%
  summarise(Message = paste0(Message, collapse = ' ')) %>%
  ungroup

5分钟的持续时间,如果你想考虑连续值之间的差异,你可以做-/P>

df %>%
  mutate(Time = mdy_hm(Time)) %>%
  group_by(Sender) %>%
  mutate(group = cumsum(difftime(Time, 
                   lag(Time, default = first(Time)), units = 'mins') > 5)) %>%
  group_by(group, .add = TRUE) %>%
  summarise(Message = paste0(Message, collapse = ' ')) %>%
  ungroup

您可以使用
ceiling\u date
创建每5分钟一组-

library(dplyr)
library(lubridate)

messageTable %>%
  group_by(Sender, Time = ceiling_date(mdy_hm(Time), unit = '5 mins')) %>%
  summarise(Message = paste0(Message, collapse = ' ')) %>%
  ungroup

5分钟的持续时间,如果你想考虑连续值之间的差异,你可以做-/P>

df %>%
  mutate(Time = mdy_hm(Time)) %>%
  group_by(Sender) %>%
  mutate(group = cumsum(difftime(Time, 
                   lag(Time, default = first(Time)), units = 'mins') > 5)) %>%
  group_by(group, .add = TRUE) %>%
  summarise(Message = paste0(Message, collapse = ' ')) %>%
  ungroup

如果输出对您有帮助,您也可以使用
runner
(用于计算滑动窗口/滚动计算的库)

my_df%
变异(msg=runner)(消息,
idx=时间,
k=‘5分钟’,
f=toString)
#>#A tibble:5 x 4
#>#组:发送方[2]
#>消息时间发送者消息
#>                                          
#>你好2018-12-14 16:27:00 300你好
#>你好吗?2018-12-14 16:29:00你好,你好吗?
#>你回答了吗?2018-12-15 12:00:00 300您回复了吗?
#>4嗨2018-12-14 16:30:00 200嗨
#>5嗨2018-12-15 16:36:00 200嗨

由(v2.0.0)于2021年5月30日创建,如果输出对您有所帮助,您也可以使用runner(用于计算滑动窗口/滚动计算的库)

my_df%
变异(msg=runner)(消息,
idx=时间,
k=‘5分钟’,
f=toString)
#>#A tibble:5 x 4
#>#组:发送方[2]
#>消息时间发送者消息
#>                                          
#>你好2018-12-14 16:27:00 300你好
#>你好吗?2018-12-14 16:29:00你好,你好吗?
#>你回答了吗?2018-12-15 12:00:00 300您回复了吗?
#>4嗨2018-12-14 16:30:00 200嗨
#>5嗨2018-12-15 16:36:00 200嗨
由(v2.0.0)于2021年5月30日创建,我们可以使用

library(dplyr)
library(lubridate)

messageTable %>%
  group_by(Sender, Time = ceiling_date(mdy_hm(Time), unit = '5 mins')) %>%
  summarise(Message = toString(Message), .groups = 'drop') 
我们可以使用

library(dplyr)
library(lubridate)

messageTable %>%
  group_by(Sender, Time = ceiling_date(mdy_hm(Time), unit = '5 mins')) %>%
  summarise(Message = toString(Message), .groups = 'drop') 

结束检查后,@Ronak提供的解决方案没有完全起作用。我使用了一些代码来实现自己的功能。Ronak的代码存在的问题是,它使用false和true进行分组,因此只能生成两组时间。事实上,我需要有多个组和多个发送者,基于时间和累积窗口

我提出的解决方案并不能真正证实R的理念,所以请随意改进它

my_df <- read.table(text = "Message             Time                    Sender
                       'hello'               '2018-12-14 16:27:00'     300
                       'how are you?'        '2018-12-14 16:34:00'     300
                       'are you good?'       '2018-12-14 16:29:00'     300
                       'do you reply?'       '2018-12-15 12:00:00'     300
                       'Have you received?'  '2018-12-15 16:34:00'     300
                       'are you good?'       '2018-12-15 16:29:00'     300
                       'Hi'                  '2018-12-14 16:30:00'     200
                       'Hi'                  '2018-12-15 16:36:00'     200
                       'Who is this?'        '2018-12-15 16:35:00'     100
                       'Hi'                  '2018-12-15 16:35:00'     100", header = T)

my_df$Time <- as.POSIXct(my_df$Time)

merged_df <- my_df %>% 
  group_by(Sender, Time) %>% 
  mutate(Message = paste0(Message, collapse = " ")) %>%
  distinct(Message, Sender, Time, .keep_all = TRUE) %>%
  group_by(Sender) %>%
  arrange(Time) %>%
  group_modify(function(table, sender) {
    counter <<- 1
    begin <<- first(table$Time)
    for (i in seq_len(nrow(table))) {
      if (isTRUE(abs(difftime(begin, table[i,]$Time, units = "mins")) > 5)) {
        counter <<- counter + 1
      }
      begin <<- table[i,]$Time
      table[i, "counter"] <- counter
    }
    table
  }) %>%
  group_by(Sender, counter, add = TRUE) %>%
  mutate(
    Message = paste0(Message, collapse = ' ')
  ) %>%
  distinct(Sender, counter, .keep_all = TRUE) %>%
  select(-counter)
my_df%
不同(消息、发件人、时间、.keep_all=TRUE)%>%
分组人(发件人)%>%
安排时间%>%
组\修改(功能(表、发送方){

计数器在结束检查后,@Ronak给出的解决方案没有完全起作用。我使用了一些代码来实现自己的实现。Ronak的代码存在的问题是,它使用false和true分组,因此只能生成两组时间。事实上,我需要根据使用c的时间,使用多个发送者创建多个组累积窗口

我提出的解决方案并不能真正证实R的理念,所以请随意改进它

my_df <- read.table(text = "Message             Time                    Sender
                       'hello'               '2018-12-14 16:27:00'     300
                       'how are you?'        '2018-12-14 16:34:00'     300
                       'are you good?'       '2018-12-14 16:29:00'     300
                       'do you reply?'       '2018-12-15 12:00:00'     300
                       'Have you received?'  '2018-12-15 16:34:00'     300
                       'are you good?'       '2018-12-15 16:29:00'     300
                       'Hi'                  '2018-12-14 16:30:00'     200
                       'Hi'                  '2018-12-15 16:36:00'     200
                       'Who is this?'        '2018-12-15 16:35:00'     100
                       'Hi'                  '2018-12-15 16:35:00'     100", header = T)

my_df$Time <- as.POSIXct(my_df$Time)

merged_df <- my_df %>% 
  group_by(Sender, Time) %>% 
  mutate(Message = paste0(Message, collapse = " ")) %>%
  distinct(Message, Sender, Time, .keep_all = TRUE) %>%
  group_by(Sender) %>%
  arrange(Time) %>%
  group_modify(function(table, sender) {
    counter <<- 1
    begin <<- first(table$Time)
    for (i in seq_len(nrow(table))) {
      if (isTRUE(abs(difftime(begin, table[i,]$Time, units = "mins")) > 5)) {
        counter <<- counter + 1
      }
      begin <<- table[i,]$Time
      table[i, "counter"] <- counter
    }
    table
  }) %>%
  group_by(Sender, counter, add = TRUE) %>%
  mutate(
    Message = paste0(Message, collapse = ' ')
  ) %>%
  distinct(Sender, counter, .keep_all = TRUE) %>%
  select(-counter)
my_df%
不同(消息、发件人、时间、.keep_all=TRUE)%>%
分组人(发件人)%>%
安排时间%>%
组\修改(功能(表、发送方){

如果消息在5分钟内发送,但时间间隔>5分钟,计数器会如何处理?例如:发件人300的消息在1:05、1:09、1:11和1:15发送。是否仍要将这四个消息合并在一起?是的,我仍要合并这些消息。我希望它基于时间范围内最新的发送消息。因此1:05+5=1:10。包括1:09。1:09+