2015-07-16 3 views
1

У меня есть dataframe (приблизительно dim 446664 X 234), который называется mydf (dput). Этот dataframe имеет столбцы REF и ALT.Как преобразовать данные генотипирования

REF имеет только одну букву в каждой строке, но ALT может иметь одну, две или даже три буквы, разделенные запятой (","), остальные столбцы (столбцы с образцами) являются столбцами, в которых мне нужно делать всю работу.

Учитывая любую букву в REF быть 0 и первая буква в ALT как 1, вторая буква 2 и третья буква 3, соответственно, мне нужно сделать функцию так, чтобы:

  1. можно заменить число во всех столбцах выборки (т. е. за исключением REF и ALT) с буквами, и если есть «./.»;

  2. Заполните их NA/NA и сверните «/», чтобы получить парные буквы в каждой ячейке.

  3. Наконец, мне нужно инвертировать все столбцы образцов по строкам (transpose), как показано на рисунке result. Спасибо!

    mydf<- 
    structure(list(REF = structure(c(1L, 4L, 3L, 2L, 3L), .Label = c("A", 
    "C", "G", "T"), class = "factor"), ALT = structure(c(6L, 6L, 
    1L, 9L, 1L), .Label = c("A", "A,C", "A,G", "A,T", "C", "C,G", 
    "C,T", "G", "G,T", "T"), class = "factor"), X860 = structure(c(1L, 
    3L, 2L, 1L, 1L), .Label = c("./.", "0/0", "0/1", "0/2", "1/1" 
    ), class = "factor"), X861 = structure(c(1L, 6L, 2L, 1L, 1L), .Label = c("./.", 
    "0/0", "0/1", "0/2", "1/1", "1/2"), class = "factor"), X862 = structure(c(6L, 
    3L, 1L, 2L, 1L), .Label = c("./.", "0/0", "0/1", "0/2", "1/1", 
    "2/2"), class = "factor")), .Names = c("REF", "ALT", "X860", 
    "X861", "X862"), row.names = c(NA, -5L), class = "data.frame") 
    

Ожидаемый результат:

X860 NANA TC GG NANA NANA 
X861 NANA CG GG NANA NANA 
X862 GG TC NANA CC NANA 
+0

В случае '1/2',' 1' означает 'REF', т.е. 'T' и' 2' для 'G' из 'C/G' в ALT? Или это просто 'CG'? Но, тогда меня путают с '0/1' как' TC'? – akrun

+2

@akrun Если я правильно понял, это индекс, основанный на 0 букв в двух столбцах 'REF' и' ALT', как если бы они были объединены. Итак, для AC, G 0 = A, 1 = C, 2 = G – Tensibai

+1

@ Tensibai Я думал, что если есть где-либо 0, это будет заменой буквы 'REF', а для других значений она основана на положение значений в «ALT», т.е. в случае 'C, G', это может быть' 1/2' или около того. Во всяком случае, сложно создать большой набор данных, чтобы попробовать с помощью 'apply' – akrun

ответ

4

Получил это, но я совершенно уверен в исполнении его:

letters <- strsplit(paste(mydf$REF,mydf$ALT,sep=","),",") # concatenate the letters to have an index to work on from the numbers 
values <- t(mydf[,3:ncol(mydf)]) # let's work on each column needing values 
nbval <- ncol(values) # Save time for later and save the length of values 

#Prepare the two temp vectors used later 
chars <- vector("character",2) 
ret <- vector("character",nbval) 

#Loop over the rows (and transpose the result) 
t(sapply(rownames(values), 
    function(x) { 
    indexes <- strsplit(values[x,],"/") # Get a list with pairs of indexes 

    for(i in 1:nbval) { # Loop over the number of columns :/ 
     for (j in 1:2) { # Loop over the pair 
     chars[j] <- ifelse(indexes[[i]][j] == ".", "NA",letters[[i]][as.integer(indexes[[i]][j])+1]) # Get NA if . or the letter with the correct index at this postion 
     } 
     ret[i] <- paste0(chars[1],chars[2]) # concatenate the two chars 
    } 
    return(ret) # return this for this row 
    } 
)) 

Выходные данные образца:

 [,1] [,2] [,3] [,4] [,5] 
X860 "NANA" "TC" "GG" "NANA" "NANA" 
X861 "NANA" "CG" "GG" "NANA" "NANA" 
X862 "GG" "TC" "NANA" "CC" "NANA" 

Обновленная версия функции (как остальная часть кода не изменяется) от комментариев:

#Loop over the rows (and transpose the result) 
t(sapply(rownames(values), 
    function(x) { 
    indexes <- strsplit(values[x,],"/") # Get a list with pairs of indexes 
    for(i in 1:nbval) { # Loop over the number of columns :/ 
     if (values[x,i] == "./.") { # test if we have ./. and if yes, set to NA 
     ret[i] <- "NA" 
     } else { # if it's not ./. then try to find the corresponding letters 
     for (j in 1:2) { # Loop over the pair 
      chars[j] <- ifelse(indexes[[i]][j] == ".", "NA",letters[[i]][as.integer(indexes[[i]][j])+1]) # Get NA if . or the letter with the correct index at this postion 
     } 
     ret[i] <- paste0(chars[1],chars[2]) # concatenate the two chars 
     } 
    } 
    return(ret) # return this for this row 
    } 
)) 

Выход:

 [,1] [,2] [,3] [,4] [,5] 
X860 "NA" "TC" "GG" "NA" "NA" 
X861 "NA" "CG" "GG" "NA" "NA" 
X862 "GG" "TC" "NA" "CC" "NA" 
+0

Огромное вам спасибо, именно то, что мне нужно! – MAPK

+0

Почему я получаю это сообщение об ошибке: NAs, введенные принуждением? – MAPK

+0

Держу пари, что у вас есть где-то 2, где нет буквы в ALT – Tensibai

3

Вот моя попытка:

#ref alt together, we will access by index of each allele 
refalt <- paste(mydf$REF,mydf$ALT,sep=",") 

#loop over for each SNP column 
t(
    sapply(3:5, function(snp){ 
    #take one SNPs 
    x <- as.character(mydf[,snp]) 
    sapply(1:length(x), function(ix){ 
     #get genotype and make numeric alleles 
     geno <- unlist(strsplit(x[ix],"/",fixed=TRUE)) 
     a1 <- as.numeric(geno[1])+1 
     a2 <- as.numeric(geno[2])+1 
     #match with refalt on ix 
     allele <- unlist(strsplit(refalt[ix],",",fixed=TRUE)) 
     #output - here I would prefer to output "NANA" as NA but it is up to you. 
     paste0(allele[a1],allele[a2]) 
    }) 
    }) 
) 

#output 
#  [,1] [,2] [,3] [,4] [,5] 
# [1,] "NANA" "TC" "GG" "NANA" "NANA" 
# [2,] "NANA" "CG" "GG" "NANA" "NANA" 
# [3,] "GG" "TC" "NANA" "CC" "NANA" 
+0

Большое вам спасибо! – MAPK

+0

Как ввести соответствующее имя столбца в каждой строке? Почему я получаю это сообщение об ошибке: NAs, введенные принуждением? – MAPK

+0

NA представила предупреждение, "." точка не может быть изменена - принудительно - к числу, поэтому она становится NA. – zx8754