2015-06-05 7 views
3

Я искал как мог, и часть моей проблемы в том, что я действительно не уверен, что именно спросить. Вот мои данные, и как я хочу, чтобы в конечном итоге:Collapse Column in R

Сейчас:

john a Yes 
john b No 
john c No 
Rebekah a Yes 
Rebekah d No 
Chase c Yes 
Chase d No 
Chase e No 
Chase f No 

Как я хотел бы, чтобы это было:

john  a,b,c Yes 
Rebekah a,d  Yes 
Chase c,d,e,f Yes 

Обратите внимание, что третий столбец говорит да, когда это первая строка с этим конкретным значением в 1-м столбце. 3-я строка не нужна, я просто использовал ее, думая, что я попытаюсь сделать все это с if и for заявлениями, но я думал, что это будет так неэффективно. Есть ли способ сделать эту работу эффективной?

ответ

6

Другим вариантом было бы (с использованием данных, упомянутые @bgoldst)

library('dplyr') 

out = df %>% 
     group_by(a) %>% 
     summarize(b = paste(unique(c(b)), collapse=","), c = "yes") 

#> out 
#Source: local data frame [3 x 3] 

#  a  b c 
#1 Chase c,d,e,f yes 
#2 Rebekah  a,d yes 
#3 john a,b,c yes 

использованием data.table

out = setDT(df)[, .(b = paste(unique(b), collapse=','), c = "yes"), by = .(a)] 

#> out 
#   a  b c 
#1: john a,b,c yes 
#2: Rebekah  a,d yes 
#3: Chase c,d,e,f yes 
+0

Этот второй data.table работал для меня очень хорошо, но я не знаю почему. Не могли бы вы помочь мне с синтаксисом? Я пытаюсь теперь избавиться от любых дубликатов. Например, если позиция 3,2 кадра данных была b, я хотел бы, чтобы позиция 1,2 нового кадра данных читала «a, b». Благодарю. –

+0

В этом случае вам нужно добавить 'unique'. проверить мой ответ Я только что отредактировал его –

4

Вы можете использовать by() сделать это:

df <- data.frame(a=c('john','john','john','Rebekah','Rebekah','Chase','Chase','Chase','Chase'), b=c('a','b','c','a','d','c','d','e','f'), c=c('Yes','No','No','Yes','No','Yes','No','No','No'), stringsAsFactors=F); 
do.call(rbind,by(df,df$a,function(x) data.frame(a=x$a[1],b=paste0(x$b,collapse=','),c=x$c[1],stringsAsFactors=F))); 
##    a  b c 
## Chase  Chase c,d,e,f Yes 
## john  john a,b,c Yes 
## Rebekah Rebekah  a,d Yes 

Edit: Вот другой подход, с использованием независимого агрегирования с помощью tapply():

key <- unique(df$a); 
data.frame(a=key,b=tapply(df$b,df$a,paste,collapse=',')[key],c=tapply(df$c,df$a,`[`,1)[key]); 
##    a  b c 
## john  john a,b,c Yes 
## Rebekah Rebekah  a,d Yes 
## Chase  Chase c,d,e,f Yes 

Edit: И еще один подход, merge() в результате нескольких звонков aggregate():

merge(aggregate(b~a,df,paste,collapse=','),aggregate(c~a,df,`[`,1)); 
##   a  b c 
## 1 Chase c,d,e,f Yes 
## 2 john a,b,c Yes 
## 3 Rebekah  a,d Yes