Разделение данных столбца и размещение их в двух последовательных строках для одного и того же наблюдения - PullRequest
1 голос
/ 17 октября 2019

У меня есть фрейм данных под названием SNP с 6000 столбцами и 500 строками. Фрейм данных выглядит следующим образом:

|sample         |   SNP1   |   SNP2   |  SNP3    |     
|:--------------|---------:|---------:|---------:|
|s1             |   AA     |   TT     |   GG     |   
|s2             |   CC     |   AT     |   AA     |   
|s3             |   AT     |   CC     |   AA     | 

Я должен изменить формат для анализа. Что я хотел бы сделать для каждого символа (я имею в виду «AA», «CC», «AT» для 2-го столбца, SNP1, например) в каждом столбце SNP, я хочу сделать 2 последовательных строки для каждого образца изатем хотите разделить символы и назначить их во вновь созданные две строки для образца. Для вашего удобства, приведенный ниже формат таблицы, который я хочу сделать:

|sample         |   SNP1   |   SNP2   |  SNP3    |     
|:--------------|---------:|---------:|---------:|
|s1             |   A      |   T      |   G      |   
|s1             |   A      |   T      |   G      |   
|s2             |   C      |   A      |   A      | 
|s2             |   C      |   T      |   A      |
|s3             |   A      |   C      |   A      |
|s3             |   T      |   C      |   A      |

Буду очень признателен, если кто-то может помочь мне решить.

Примечание: я добавил скриншотдатафрейм, если формат, который я добавил, смещен, я новичок здесь.

Ответы [ 2 ]

1 голос
/ 17 октября 2019

Вот изящное data.table решение.

Вы можете посчитать этот пост поучительным. Пример переполнения стека, иллюстрирующий tstrsplit

require(data.table)
df = data.table(sample=c("s1","s2","s3"),
   SNP1=c("AA","CC","AT"),
   SNP2=c("TT","AT","CC"),
   SNP3=c("GG","AA","AA"))


# get the names of the relevant columns

x=grep("SNP",names(df),value = TRUE)

# split each column.  The 'by' functionality will 
# manage the stacking of the results.

df[,lapply(.SD,tstrsplit,'',fixed=TRUE),.SDcols=x,by=sample]

output:

 |sample |SNP1 |SNP2 |SNP3 |
 |:------|:----|:----|:----|
 |s1     |A    |T    |G    |
 |s1     |A    |T    |G    |
 |s2     |C    |A    |A    |
 |s2     |C    |T    |A    |
 |s3     |A    |C    |A    |
 |s3     |T    |C    |A    |

Если строки были фиксированной длины, но не обязательно длиной 2, это все равно, кажется, работает,Я НЕ проверял это на пустых строках. caveat emptor

1 голос
/ 17 октября 2019

Вот одно из возможных решений с использованием пакета tidyverse и регулярных выражений:

library(tidyverse)

snp <- data.frame(sample = c("s1", "s2", "s3"),
                  SNP1 = c("AA", "CC", "AT"),
                  SNP2 = c("TT", "AT", "CC"),
                  SNP3 = c("GG", "AA", "AA"))


snp %>% mutate_at(-1, ~str_extract(.x, "^.")) %>%
  bind_rows(mutate_at(snp, -1, ~str_extract(.x, ".$"))) %>%
  arrange(sample)

  sample SNP1 SNP2 SNP3
1     s1    A    T    G
2     s1    A    T    G
3     s2    C    A    A
4     s2    C    T    A
5     s3    A    C    A
6     s3    T    C    A

Краткое объяснение: сначала я извлекаю первую букву (^.) из всех столбцов, кроме первого (отсюда -1). Затем я извлекаю последнюю букву (.$) из всех столбцов, кроме первой. Наконец, я вставил эти два data.frames вместе и переставил результат, используя arrange.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...