在一个中删除重复值后,更好/更快地连接两列?

时间:2016-01-06 21:37:34

标签: r string performance

我有一个包含两列的数据框,最后一列有重复:

 #reproducible data
    my.df <- data.frame(nr = paste(1:6,1,sep="_"),
                        text = c("aa","bb","aa",NA,"bb","xxxx"))
   nr text
1 1_1   aa
2 2_1   bb
3 3_1   aa
4 4_1 <NA>
5 5_1   bb
6 6_1 xxxx

我想对第一列中的值进行分组,然后添加第二列的值。我找到了一种方法:

apply(aggregate(nr~text, my.df, FUN=function(x) paste0(x, collapse = "/"))[,c(2,1)],1,FUN=function(x) paste(x[1],x[2], sep = ": "))

给出了:

"1_1/3_1: aa" "2_1/5_1: bb" "6_1: xxxx"

这是我想要的结果,但代码似乎相当长。我觉得必须有更好的,也许更快的方法来做到这一点?

是的,NA应该从结果中移除。

编辑:

感谢所有答案。我认为有一个比我自己更容易的解决方案,但显然没有。可读性是(恕我直言)非常主观,所以我做了一个基准:

microbenchmark(RHA(my.df),Heroka_DT(my.df),Heroka_Base(my.df),Jubbles(my.df),times=100L)

Unit: milliseconds
               expr       min        lq      mean    median        uq
         RHA(my.df)  9.116587  9.315988  9.662611  9.572361 10.036792
   Heroka_DT(my.df) 12.148374 12.448035 13.009290 12.766685 13.475480
 Heroka_Base(my.df)  2.947448  6.910890  7.475239  7.172847  7.614657
     Jubbles(my.df) 16.615067 40.609642 42.265267 41.799625 43.056632
      max neval
 10.78943   100
 21.12477   100
 15.97665   100
 61.68414   100
在这种情况下,基本解决方案显然比其他解决方案更快。由于Heroka有最短和最快的解决方案,我会接受他的回答。

3 个答案:

答案 0 :(得分:6)

你可以使用data.table,它有点短,(恕我直言)更具可读性:

library(data.table)

res <- setDT(my.df)[!is.na(text),.(output=sprintf("%s: %s",paste(nr,collapse="/"),text)),text][,output]
res

> res
[1] "1_1/3_1: aa" "2_1/5_1: bb" "6_1: xxxx"  

我们可以在base-R中做一些非常相似的事情:

sapply(split(my.df, my.df$text),function(x){with(x, sprintf("%s: %s",paste(nr, collapse="/"),text[1]))})

           aa            bb          xxxx 
"1_1/3_1: aa" "2_1/5_1: bb"   "6_1: xxxx" 

答案 1 :(得分:2)

data.table更易读(IMO)但不短......)

# dplyr_0.4.3
library(dplyr)

(my.df %>%
filter(!(is.na(text))) %>%
group_by(text) %>%
summarize(my.nrs = paste(nr, collapse = "/")) %>%
ungroup() %>%
mutate(res = paste(my.nrs, text, sep = ": ")))$res

答案 2 :(得分:2)

我喜欢Jubbles dplyr方法,但是,我认为通过使用非常有用的dplyr::do()函数可以使它更具可读性。

my.df %>%
  group_by(text) %>%
  do(new_nr = paste(.$nr, collapse = "/")) %>%
  do(done = paste(.$new_nr, .$text, sep = ": "))

dplyr::do()函数的一个注释。当它不是管道链的一部分时,它需要两个参数,数据和函数,即do(.data, .fun)。但是,当您进行管道传输时,数据会像往常一样自动放入第一个参数中。但是,与其他dplyr函数不同,您必须引用已传递给do()的数据。您可以像往常一样使用$执行此操作,但是在数据名称中,您将引用作为do传递给.的数据,因此.$。换句话说,do()不采用其他dplyr函数采用的非标准评估方法。这当然是有目的地完成的,因为它增加了do()功能的功能。例如,它允许您拨打lm