Achal Neupane
Achal Neupane

Reputation: 5719

Extract values in two different columns matching in other columns in R

I have this matrix called mymat(approx dim of 446664 X 234). It has REF and ALT columns where they could have any of A,T,G,C letters (only one letter). In the columns ending with .GT, I want to replace these letters. The condition to match is, if there is 0, I want to replace it with the letter in REF column and if there is 1 then I want to replace it with the letter in ALT column. If there is NA, I want to replace it with "0" "0" (i.e., zero space zero). Finally I need to invert all the .GT columns across the rows (transpose) as shown in the result. In the result, everything is separated by space.

 mymat<-structure(c("G", "A", "C", "A", "G", "A", "C", "T", "G", "A", 
"1/1", "0/0", "0/0", "NA", "NA", "0,15", "8,0", "8,0", "NA", 
"NA", "1/1", "0/1", "0/0", "NA", "NA", "0,35", "12,12", "15,0", 
"NA", "NA"), .Dim = 5:6, .Dimnames = list(c("chrX:133511988:133511988:G:A:snp", 
"chrX:133528116:133528116:A:C:snp", "chrX:133528186:133528186:C:T:snp", 
"chrX:133560301:133560301:A:G:snp", "chrX:133561242:133561242:G:A:snp"
), c("REF", "ALT", "02688.GT", "02688.AD", "02689.GT", "02689.AD"
)))

result

02688.GT  A A A A C C 0 0 0 0
02689.GT  A A A C C C 0 0 0 0 

Upvotes: 2

Views: 82

Answers (3)

Steven Beaupr&#233;
Steven Beaupr&#233;

Reputation: 21641

You could try:

library(dplyr)
library(stringi)

## convert to data.frame 
data.frame(mymat, check.names = FALSE) %>%
  ## replace the values ("0", "1", "/", "NA") in all columns ending with ".GT" with
  ## the corresponding values in "REF" and "ALT" (" " for "/" and "0 0" for "NA")
  mutate_each(funs(stri_replace_all(., REF, fixed = "0")), ends_with(".GT")) %>%
  mutate_each(funs(stri_replace_all(., ALT, fixed = "1")), ends_with(".GT")) %>%
  mutate_each(funs(stri_replace_all(., " ", fixed = "/")), ends_with(".GT")) %>%
  mutate_each(funs(stri_replace_all(., "0 0", fixed = "NA")), ends_with(".GT")) %>%
  ## keep only the columns ending with ".GT"
  select(ends_with(".GT")) %>%
  ## transpose the results
  t()

Which gives:

         [,1]  [,2]  [,3]  [,4]  [,5] 
02688.GT "A A" "A A" "C C" "0 0" "0 0"
02689.GT "A A" "A C" "C C" "0 0" "0 0"

Upvotes: 2

Achal Neupane
Achal Neupane

Reputation: 5719

I am posting my own answer, but is really slow so need further optimization.

       letters <- strsplit(paste(mymat[,"REF"],mymat[,"ALT"],sep=","),",") # concatenate the letters to have an index to work on from the numbers
values <- t(mymat[,c(which(colnames(mymat)%in%lapply(all.samples,function(x)(paste(x,"GT",sep=".")))))]) # working on each column needing values
nbval <- ncol(values) # Keeping track of total number of columns and saving the length of values 

#Preparing the two temp vectors to be used below
chars <- vector("character",2) 
ret <- vector("character",nbval)

#Loop over the rows (and transpose the result)
mydata<-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] == "NA", 0,letters[[i]][as.integer(indexes[[i]][j])+1]) # Get '0' if "NA" or the letter with the correct index at this postion
                     }
                     ret[i] <- paste(chars[1],chars[2], sep=" ") # concatenate the two chars
                   }
                   return(ret) # return this for this row
                 }
))

Upvotes: 0

atiretoo
atiretoo

Reputation: 1902

So this is only a partial answer, and I have no idea how well it will work with > 200000 rows. But maybe someone cleverer will figure out how to do it better.

temp1 = strsplit(mymat[,3],"/")
reps = sapply(temp1,length)
refalt = data.frame(REF = rep(mymat[,1],times=reps),ALT = rep(mymat[,2],times=reps),ZERO = "0 0")
GT1 = unlist(temp1)
GT1[GT1=="NA"] = "2"
GT1 = as.numeric(GT1)+1
paste(refalt[cbind(1:8,GT1)]," ")

It is incomplete because we need to wrap it up in a function that can be passed to apply() or lapply(), and capture the variable name at the start of the line.

Upvotes: 0

Related Questions