我有一个包含两列的数据框,最后一列有重复:
#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有最短和最快的解决方案,我会接受他的回答。
答案 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
。