Как переместить данные из столбцов в строки, по два столбца одновременно? - PullRequest
0 голосов
/ 23 декабря 2018

Я пытаюсь транспонировать данные из столбцов в строки, но делаю только два столбца за раз по всем строкам.Но пропустив первые 2 столбца.

Мой начальный фрейм данных выглядит так: каждая строка является генетическим маркером.Первые два столбца содержат информацию о местонахождении этого маркера, следующие столбцы содержат информацию о нуклеотидах ДНК для отдельных лиц с этим конкретным маркером.

Однако у каждого человека имеется два нуклеотида на каждый маркер.

Нули обозначают отсутствующиезначения.

Таким образом, в этом фрейме данных есть 5 генетических маркеров в строке и всего 3 человека.(Индивидуум 1 имеет оба нуклеотида, определенных в V1 и V2, Индивидуум 2 имеет их в V3 и V4 и т. Д.).

group pos V1 V2 V3 V4 V5 V6 
1     10  A  A  G  G  T  T
2     11  C  C  G  G  A  A
3     12  T  T  T  A  C  G
4     13  0  0  0  A  C  G
5     14  G  T  0  0  C  A    

Я хочу изменить порядок данных, чтобы индивидуумы были в строке, а генетический маркер - в столбце.Однако я хочу сохранить «пары» нуклеотидов вместе и игнорировать первые два столбца.

Я хочу выложить этот файл:

A A C C T T 0 0 G T 
G G G G T A 0 A 0 0 
T T A A C G C G C A 

Пока что я написал цикл, который работает.Но он слишком медленный, он не может обрабатывать более 40 тыс. Строк.Мои фреймы данных могут быть 500K строк и 130 столбцов.

oi2 <- list(NA) # create an empty list assigned to "oi2"
for(j in seq(3, ncol(data), 2)) { # create a sequence of data subset to keep 2 columns together 
oi <- "" # create an empty vector 
  for(i in 1:nrow(data)) { # do it for every row 
    oi <- c(oi, as.character(data[i,j]), as.character(data[i,j+1])) # add data together in a row 
  } # loop ends for row loop, were still inside first loop 
 oi <- oi[-1] # remove first "" element 
  oi2[[j-2]] <- oi # once oi is created, save to list "oi2", assigned to j-2 position in list 
} # loop closes 
oi3 <- oi2[!sapply(oi2, is.null)] # remove null elements in data frame 
# unlist the list and then convert to matrix, and then to data frame 
df <- data.frame(matrix(unlist(oi2), nrow=length(oi3), byrow=T, 
                          ncol = length(oi3[[1]]))) 

Есть ли более элегантный способ сделать это, который был бы быстрее и мог обрабатывать большие кадры данных?

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

1) При условии, что входные данные DF, воспроизводимые в примечании в конце, преобразуют все, кроме первых 2 столбцов, в матрицу 5x6, а затем преобразуют это в массив 5x2x3, переставляют его размеры и изменяют формуобратно в матрицу 3х10.Пакеты не используются.

m <- as.matrix(DF[-(1:2)]
nr <- nrow(m) # 5
nc <- ncol(m) # 6

matrix(aperm(array(m, c(nr, 2, nc/2)), c(3, 2, 1)), nc/2)

, давая:

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] "A"  "A"  "C"  "C"  "T"  "T"  "0"  "0"  "G"  "T"  
[2,] "G"  "G"  "G"  "G"  "T"  "A"  "0"  "A"  "0"  "0"  
[3,] "T"  "T"  "A"  "A"  "C"  "G"  "C"  "G"  "C"  "A" 

2) Разновидностью вышеупомянутого является первая транспонирование m, преобразование его вмассив, а затем переставить только первые два измерения, возвращаясь к матрице в конце.

matrix(aperm(array(t(m), c(2, nc/2, nr)), c(2, 1, 3)), nc/2)

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] "A"  "A"  "C"  "C"  "T"  "T"  "0"  "0"  "G"  "T"  
[2,] "G"  "G"  "G"  "G"  "T"  "A"  "0"  "A"  "0"  "0"  
[3,] "T"  "T"  "A"  "A"  "C"  "G"  "C"  "G"  "C"  "A"  

Примечание

Lines <- "
group pos V1 V2 V3 V4 V5 V6 
1     10  A  A  G  G  T  T
2     11  C  C  G  G  A  A
3     12  T  T  T  A  C  G
4     13  0  0  0  A  C  G
5     14  G  T  0  0  C  A"
DF <- read.table(text = Lines, header = TRUE, as.is = TRUE)
0 голосов
/ 23 декабря 2018

Это, вероятно, не самый эффективный способ, но лучшее, что я мог придумать в этот час (1:00)

пример данных

library( data.table )
dt <- fread("group pos V1 V2 V3 V4 V5 V6 
1     10  A  A  G  G  T  T
2     11  C  C  G  G  A  A
3     12  T  T  T  A  C  G
4     13  0  0  0  A  C  G
5     14  G  T  0  0  C  A", header = TRUE, stringsAsFactors = FALSE)

код

library( tidyverse )
#paste together the rows of the dt (minus col 1 and 2)
l1 <- pmap( dt[, -c(1,2)], paste, sep = '')
#split the values in the list into pairs of 2 letters
l2 <- lapply( l1, strsplit, "(?<=.{2})", perl = TRUE )
#unlist
data <- unlist(l2)
#build a new matrix with three rows
matrix( data, nrow = 3) %>% apply( ., 1, paste, collapse = "")

выход

#[1] "AACCTT00GT" "GGGGTA0A00" "TTAACGCGCA"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...