Объединить несколько столбцов в строки, разделенные запятыми, по группе

#r

#r

Вопрос:

Справочная информация: Я нахожусь в процессе аннотирования SNP из GWAS в организме без особых аннотаций. Я использую объединенную таблицу tBLASTn из UCSC вместе с biomaRt, чтобы сопоставить каждый SNP с вероятным геном (ами).

У меня есть фрейм данных, который выглядит следующим образом:

             SNP   hu_mRNA     gene
 chr1.111642529 NM_002107    H3F3A
 chr1.111642529 NM_005324    H3F3B
 chr1.111801684 BC098118     <NA>
 chr1.111925084 NM_020435    GJC2
  chr1.11801605 AK027740     <NA>
  chr1.11801605 NM_032849    C13orf33
 chr1.151220354 NM_018913    PCDHGA10
 chr1.151220354 NM_018918    PCDHGA5
  

В итоге я хотел бы получить одну строку для каждого SNP, а гены и hu_mRNAs разделять запятыми. Вот что мне нужно:

             SNP            hu_mRNA    gene
 chr1.111642529 NM_002107,NM_005324   H3F3A
 chr1.111801684  BC098118,NM_020435   GJC2
  chr1.11801605  AK027740,NM_032849   C13orf33
 chr1.151220354 NM_018913,NM_018918   PCDHGA10,PCDHGA5
  

Теперь я знаю, что могу сделать это одним движением руки в perl, но я действительно хочу сделать все это в R. Есть предложения?

Ответ №1:

Вы могли бы сделать это в одной строке, используя plyr , поскольку это классическая split-apply-combine проблема. Вы разбиваете с помощью SNP , применяете paste с collapse помощью и собираете фрагменты обратно во фрейм данных.

 plyr::ddply(x, .(SNP), colwise(paste), collapse = ",")
  

Если вы хотите выполнить data изменение формы в R в flick of a wrist , изучите plyr и reshape2 :). Еще одно простое решение с использованием data.table , действительно полезное, если вы имеете дело с огромными объемами данных.

 data.table::data.table(x)[,lapply(.SD, paste, collapse = ","),'SNP']
  

Ответ №2:

Вы можете использовать aggregate with paste для каждого из них и merge в конце:

 x <- structure(list(SNP = structure(c(1L, 1L, 2L, 3L, 4L, 4L, 5L, 
5L), .Label = c("chr1.111642529", "chr1.111801684", "chr1.111925084", 
"chr1.11801605", "chr1.151220354"), class = "factor"), hu_mRNA = structure(c(3L, 
4L, 2L, 7L, 1L, 8L, 5L, 6L), .Label = c("AK027740", "BC098118", 
"NM_002107", "NM_005324", "NM_018913", "NM_018918", "NM_020435", 
"NM_032849"), class = "factor"), gene = structure(c(4L, 5L, 1L, 
3L, 1L, 2L, 6L, 7L), .Label = c("<NA>", "C13orf33", "GJC2", "H3F3A", 
"H3F3B", "PCDHGA10", "PCDHGA5"), class = "factor")), .Names = c("SNP", 
"hu_mRNA", "gene"), class = "data.frame", row.names = c(NA, -8L
))

a1 <- aggregate(hu_mRNA~SNP,data=x,paste,sep=",")
a2 <- aggregate(gene~SNP,data=x,paste,sep=",")
merge(a1,a2)
             SNP              hu_mRNA              gene
1 chr1.111642529 NM_002107, NM_005324      H3F3A, H3F3B
2 chr1.111801684             BC098118              <NA>
3 chr1.111925084            NM_020435              GJC2
4  chr1.11801605  AK027740, NM_032849    <NA>, C13orf33
5 chr1.151220354 NM_018913, NM_018918 PCDHGA10, PCDHGA5
  

Комментарии:

1. Блестяще!! Спасибо! Я не знал aggregate функции. Я немного изменил, чтобы убрать пробелы после запятых, например: a1 <- aggregate(hu_mRNA~SNP,data=x,paste,collapse=",") a2 <- aggregate(gene~SNP,data=x,paste,collapse=",")

2. @caddymob Хороший вызов, кажется, что sep на самом деле это не имеет никакого эффекта в этом случае, только collapse действует.

3. @Джеймс. Решение Габора предполагало, что будет работать однострочный вариант с collapse="," .

Ответ №3:

Сначала настройте тестовые данные. Обратите внимание, что мы сделали столбцы "character" классовыми, а не "factor" с помощью as.is=TRUE :

 Lines <- "SNP   hu_mRNA     gene
 chr1.111642529 NM_002107    H3F3A
 chr1.111642529 NM_005324    H3F3B
 chr1.111801684 BC098118     <NA>
 chr1.111925084 NM_020435    GJC2
  chr1.11801605 AK027740     <NA>
  chr1.11801605 NM_032849    C13orf33
 chr1.151220354 NM_018913    PCDHGA10
 chr1.151220354 NM_018918    PCDHGA5"
cat(Lines, "n", file = "data.txt")
DF <- read.table("data.txt", header = TRUE, na.strings = "<NA>", as.is = TRUE)
  

Теперь попробуйте этот aggregate оператор:

 > aggregate(. ~ SNP, DF, toString)
             SNP              hu_mRNA              gene
1 chr1.111642529 NM_002107, NM_005324      H3F3A, H3F3B
2 chr1.111925084            NM_020435              GJC2
3  chr1.11801605            NM_032849          C13orf33
4 chr1.151220354 NM_018913, NM_018918 PCDHGA10, PCDHGA5
  

Комментарии:

1. И по тому же принципу это должно увенчаться успехом: aggregate(. ~ SNP, DF, paste, collapse=",")

Ответ №4:

Это также можно решить с помощью операций reshape2 ‘s melt и dcast . При таком подходе melt сначала преобразуются данные в «длинный» формат, а затем значения dcast редактируются с помощью той же операции, paste(..., collapse = ",") :

 library(reshape2)

x <- read.table(
  stringsAsFactors = FALSE,
  header = TRUE,
  na.strings = "<NA>",
  text = "            SNP   hu_mRNA     gene
 chr1.111642529 NM_002107    H3F3A
 chr1.111642529 NM_005324    H3F3B
 chr1.111801684 BC098118     <NA>
 chr1.111925084 NM_020435    GJC2
  chr1.11801605 AK027740     <NA>
  chr1.11801605 NM_032849    C13orf33
 chr1.151220354 NM_018913    PCDHGA10
 chr1.151220354 NM_018918    PCDHGA5")

(xm <-melt(x, id.vars = "SNP", na.rm = TRUE))
##               SNP variable     value
## 1  chr1.111642529  hu_mRNA NM_002107
## 2  chr1.111642529  hu_mRNA NM_005324
## 3  chr1.111801684  hu_mRNA  BC098118
## 4  chr1.111925084  hu_mRNA NM_020435
## 5   chr1.11801605  hu_mRNA  AK027740
## 6   chr1.11801605  hu_mRNA NM_032849
## 7  chr1.151220354  hu_mRNA NM_018913
## 8  chr1.151220354  hu_mRNA NM_018918
## 9  chr1.111642529     gene     H3F3A
## 10 chr1.111642529     gene     H3F3B
## 12 chr1.111925084     gene      GJC2
## 14  chr1.11801605     gene  C13orf33
## 15 chr1.151220354     gene  PCDHGA10
## 16 chr1.151220354     gene   PCDHGA5

(xc <- dcast(xm, SNP~variable, fun.aggregate = paste, collapse = ","))
##              SNP             hu_mRNA             gene
## 1 chr1.111642529 NM_002107,NM_005324      H3F3A,H3F3B
## 2 chr1.111801684            BC098118                 
## 3 chr1.111925084           NM_020435             GJC2
## 4  chr1.11801605  AK027740,NM_032849         C13orf33
## 5 chr1.151220354 NM_018913,NM_018918 PCDHGA10,PCDHGA5
  

Ответ №5:

Вот dplyr решение, какой IHMO является наиболее читаемым:

 library(dplyr)

x %>%
  group_by(SNP) %>%
  summarize(
    genes = paste(gene, collapse = ','),
    hu_mRNA = paste(hu_mRNA, collapse = ',')
  )
  

Результат:

 Source: local data frame [5 x 3]

             SNP            genes             hu_mRNA
          (fctr)            (chr)               (chr)
1 chr1.111642529      H3F3A,H3F3B NM_002107,NM_005324
2 chr1.111801684             <NA>            BC098118
3 chr1.111925084             GJC2           NM_020435
4  chr1.11801605    <NA>,C13orf33  AK027740,NM_032849
5 chr1.151220354 PCDHGA10,PCDHGA5 NM_018913,NM_018918