连接行并删除连续的重复项或重复元素

Concatenating rows and dropping the successive repetitions or repeating elements

我有一个数据框如下,我想根据票号连接序列中的行(如果连续重复则删除它们)并确定它们是如何传递给人们的。

    ticket<- c("1", "1", "1", "2", "2", "2", "2")
    name<- c("Olg", "Jan", "Jan", "Olg", "Jan", "Jan","Olg")
    df<- data.frame(ticket, name)

我想创建一个名为序列的变量列,它提供路径并抑制连续重复,如图所示(Olg-Jan-Jan 到 Olg-Jan 和 Olg-Jan-Jan-Olg 到 Olg-Jan-Olg ).有什么建议么?谢谢!

   seq<- c("Olg-Jan", "Olg-Jan", ""Olg-Jan", "Olg-Jan-Olg","Olg-Jan-Olg","Olg-Jan-Olg" )

name 是一个因子(如果不是,我们可以将其转换为因子)因此我们使用基础数字因子代码来检查连续的重复项并删除它们。我们使用 dplyr 以便我们可以轻松地按 ticket 分组并使用链接运算符 (%>%).

将函数链接在一起
library(dplyr) 

df %>% group_by(ticket) %>%
   filter(c(1, diff(as.numeric(name))) !=0) %>%
   summarise(sequence = paste(name, collapse="-"))
  ticket    sequence
1      1     Olg-Jan
2      2 Olg-Jan-Olg

如果你想保留原始数据框的所有行并只添加序列,那么你可以left_join将上面的输出left_join到你的原始数据框:

df = df %>% 
  left_join(df %>% group_by(ticket) %>%
              filter(c(1, diff(as.numeric(name))) !=0) %>%
              summarise(sequence = paste(name, collapse="-")))
  ticket name    sequence
1      1  Olg     Olg-Jan
2      1  Jan     Olg-Jan
3      1  Jan     Olg-Jan
4      2  Olg Olg-Jan-Olg
5      2  Jan Olg-Jan-Olg
6      2  Jan Olg-Jan-Olg
7      2  Olg Olg-Jan-Olg

如果我没理解错的话....

> df_to_list <- split(df, df$ticket)
> df_to_list
$`1`
  ticket name
1      1  Olg
2      1  Jan
3      1  Jan

$`2`
  ticket name
4      2  Olg
5      2  Jan
6      2  Jan
7      2  Olg

现在我们要循环并取消列出名称,然后删除连续出现相同名称的情况,然后绑定。

new_df <- lapply(df_to_list, function(i){

  a <- as.character(unlist(i[['name']]))

  endr <- length(a) - 1
  b <- sapply(1:endr, function(x){
    a[x] != a[x+1]
  })

  c <- a[b]

  paste0(c, collapse = "-")

}) %>% melt %>% select(ticket = L1, seq = value)

> new_df
  ticket         seq
1      1     Olg-Jan
2      2 Olg-Jan-Olg

这就是你想要的吗?

注意:使用 group_by 方法与这种方法的速度差异产生了有趣的输出时间。我将集合复制到 14000 行并将新数据框命名为 addf 并将两个解决方案包装到单独的函数 using_group 和 `no_group 中。

> system.time(using_group(addf))
   user  system elapsed 
  0.012   0.000   0.011 
> system.time(no_group(addf))
   user  system elapsed 
  0.004   0.000   0.004