R: объединить одинаковые идентификаторы в кадре данных - PullRequest
4 голосов
/ 10 мая 2011

У меня есть датафрейм с 2 столбцами, одним идентификатором и столбцом с именами. Каждый идентификатор несколько раз присутствует в идентификаторе столбца (см. Ниже).

 ID           Names
uc001aag.1  DKFZp686C24272
uc001aag.1  DQ786314
uc001aag.1  uc001aag.1
uc001aah.2  AK056232
uc001aah.2  FLJ00038
uc001aah.2  uc001aah.1
uc001aah.2  uc001aah.2
uc001aai.1  AY217347

Теперь я хочу создать такой фрейм данных:

 ID           Names
uc001aag.1  DKFZp686C24272 | DQ786314 | uc001aag.1
uc001aah.2  AK056232 | FLJ00038 | uc001aah.1 | uc001aah.2
uc001aai.1  AY217347

Кто-нибудь может мне помочь?

Ответы [ 2 ]

4 голосов
/ 10 мая 2011

Aggregate довольно быстрый, но вы можете использовать более подходящее решение для распараллеливания кода. Это легко сделать в Windows, используя snowfall:

require(snowfall)
sfInit(parallel=TRUE,cpus=2)
sfExport("Data")

ID <- unique(Data$ID)
CombNames <- sfSapply(ID,function(i){
    paste(Data$Names[Data$ID==i],collapse=" | ")
})
data.frame(ID,CombNames)
sfStop()

Параллельная версия даст вам дополнительное ускорение, но единственное решение Sapply на самом деле медленнее, чем агрегат. Tapply немного быстрее, но его нельзя распараллелить, используя снегопад. на моем компьютере:

n <- 3000
m <- 3
Data <- data.frame( ID = rep(1:n,m),
                    Names=rep(LETTERS[1:m],each=n))
 # using snowfall for parallel sapply    
 system.time({
   ID <- unique(Data$ID)
   CombNames <- sfSapply(ID,function(i){
     paste(Data$Names[Data$ID==i],collapse=" | ")
   })
   data.frame(ID,CombNames)
 }) 
   user  system elapsed 
   0.02    0.00    0.33 

 # using tapply
 system.time({
   CombNames <- tapply(Data$Names,Data$ID,paste,collapse=" | ")
   data.frame(ID=names(CombNames),CombNames)
 })
   user  system elapsed 
   0.44    0.00    0.44 

 # using aggregate
 system.time(
   aggregate(Names ~ ID, data=Data, FUN=paste, collapse=" | ")
 )
   user  system elapsed 
   0.47    0.00    0.47 

 # using the normal sapply
 system.time({
   ID <- unique(Data$ID)
   CombNames <- sapply(ID,function(i){
     paste(Data$Names[Data$ID==i],collapse=" | ")
   })
   data.frame(ID,CombNames)
 })
   user  system elapsed 
   0.75    0.00    0.75 

Примечание:

Для справки, лучшее решение для сапплей было бы:

CombNames <- sapply(split(Data$Names,Data$ID),paste,collapse=" | ")
data.frame(ID=names(CombNames),CombNames)

, что эквивалентно tapply. Но распараллеливание этого на самом деле медленнее, так как вам нужно перемещать больше данных внутри sfSapply. Скорость зависит от копирования набора данных в каждый процессор. Это то, что вы должны иметь в виду, когда ваш набор данных огромен: вы заплатите за скорость, используя больше памяти.

4 голосов
/ 10 мая 2011

Вы можете использовать aggregate:

R> aggregate(Names ~ ID, data=tmp, FUN=paste, collapse=" | ")
          ID                                         Names
1 uc001aag.1        DKFZp686C24272 | DQ786314 | uc001aag.1
2 uc001aah.2 AK056232 | FLJ00038 | uc001aah.1 | uc001aah.2
3 uc001aai.1                                      AY217347
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...