2012-04-27 19 views
5

Aquí es pequeño ejemplo:traducción (recodificación) error en r

X1 <- c("AC", "AC", "AC", "CA", "TA", "AT", "CC", "CC") 
X2 <- c("AC", "AC", "AC", "CA", "AT", "CA", "AC", "TC") 
X3 <- c("AC", "AC", "AC", "AC", "AA", "AT", "CC", "CA") 
mydf1 <- data.frame(X1, X2, X3) 

trama de datos de entrada

X1 X2 X3 
1 AC AC AC 
2 AC AC AC 
3 AC AC AC 
4 CA CA AC 
5 TA AT AA 
6 AT CA AT 
7 CC AC CC 
8 CC TC CA 

La función

# Function 
atgc <- function(x) { 
xlate <- c("AA" = 11, "AC" = 12, "AG" = 13, "AT" = 14, 
"CA"= 12, "CC" = 22, "CG"= 23,"CT"= 24, 
"GA" = 13, "GC" = 23, "GG"= 33,"GT"= 34, 
"TA"= 14, "TC" = 24, "TG"= 34,"TT"=44, 
"ID"= 56, "DI"= 56, "DD"= 55, "II"= 66 
) 
    x = xlate[x] 
} 
outdataframe <- sapply (mydf1, atgc) 
outdataframe 
    X1 X2 X3 
AA 11 11 12 
AA 11 11 12 
AA 11 11 12 
AG 13 13 12 
CA 12 12 11 
AC 12 13 13 
AT 14 11 12 
AT 14 14 14 

problema, AC es no eaqual a 12 en salida en lugar de 11, de manera similar para otros. ¡Solo lío!

(exta: También no sé cómo deshacerse de los rownames.)

+2

La solución más simple para usted podría ser simplemente editar 'x = xlate [x]' a 'x = xlate [as.character (x)]', ya que ese es el bit que está causando el error. (Los 'x' son vectores de clase 'factor', y los valores enteros del factor (en lugar de las cadenas de caracteres asociadas) se usan en la indexación). –

+2

Además, para deshacerse de los nombres de fila, simplemente haga' rownames (mydf) <- NULL'. –

Respuesta

4

Sólo tiene que utilizar apply y la transposición:

t(apply (mydf1, 1, atgc)) 

Para utilizar sapply, a continuación, utilizar:

  1. stringsAsFactors=FALSE al crear su marco de datos, es decir,

    mydf1 <- data.frame(X1, X2, X3, stringsAsFactors=FALSE) 
    

    (@joran gracias) o

  2. Cambie la última línea de su función para: x = xlate[as.vector(x)]

+0

Creo que 'sapply' funcionará si usan' stringsAsFactors = FALSE' para evitar los factores, pero creo que esto es probablemente mejor. – joran

+0

@JohnCLK, también podría ver la función 'recode' en el paquete' car', que hace lo que creo que quiere que haga su función 'atgc'. – BenBarnes

1

La función `partido puede utilizar argumentos de los factores con un vector de concordancia de objeto que es el "carácter" clase:

atgc <- function(fac){ c(11, 12, 13, 14, 
12, 22, 23, 24, 
13, 23, 33, 34, 
14, 24, 34,44, 
56, 56, 55, 66)[ 
match(fac, 
    c("AA", "AC", "AG", "AT", 
    "CA", "CC", "CG","CT", 
    "GA", "GC", "GG","GT" , 
    "TA", "TC", "TG","TT", 
    "ID", "DI", "DD", "II")) 
       ]} 
#The match function returns an index that is designed to pull from a vector. 
sapply(mydf1, atgc) 
    X1 X2 X3 
[1,] 12 12 12 
[2,] 12 12 12 
[3,] 12 12 12 
[4,] 12 12 12 
[5,] 14 14 11 
[6,] 14 12 14 
[7,] 22 12 22 
[8,] 22 24 12 
0

De esta manera, solo debe proporcionar valores de reemplazo para cada letra individual en la matriz, sin tener que volver a verificar m Asegúrese de considerar todas las combinaciones y hacerlas coincidir correctamente, aunque con su ejemplo las combinaciones son limitadas.

lista Definir con valores y su sustituto:

trans <- list(c("A","1"),c("C","2"),c("G","3"),c("T","4"), 
    c("I","6"),c("D","5")) 

Definir función de reemplazo usando gsub()

atgc2 <- function(myData, x) gsub(x[1], x[2], myData) 

crean una matriz con los valores sustituidos (en este caso, la conversión de mydf1 a una matriz de regresar valores de caracteres como desee para gsub(), pero le recomendamos verificar si esto funciona con otros datos antes de continuar)

mymat <- Reduce(atgc2, trans, init = as.matrix(mydf1)) 

Los valores en mymat todavía están en el orden en que aparecieron originalmente, por lo "AC" = "12" y "CA" = "21", por lo reordenarlos (y las convierten en valores numéricos)

ansVec <- sapply(strsplit(mymat, split = ""), 
    function(x) as.numeric(paste0(sort(as.numeric(x)), collapse = ""))) 

El objeto ansVec es una vector, así que conviértalo nuevamente en un dato.marco

(mydf2 <- data.frame(matrix(ansVec, nrow = nrow(mydf1)))) 
# X1 X2 X3 
# 1 12 12 12 
# 2 12 12 12 
# 3 12 12 12 
# 4 12 12 12 
# 5 14 14 11 
# 6 14 12 14 
# 7 22 12 22 
# 8 22 24 12 

Para esta situación, las otras respuestas son definitivamente más rápidas. Sin embargo, a medida que las operaciones de reemplazo se vuelven más complejas, creo que esta solución podría ofrecer algunos beneficios. Uno de los aspectos que este método no abordaría, sin embargo, sería verificar la cadena "ATTGCG" para "ATT" y "TTG".

0

En realidad, creo que desea representar sus vectores originales como factores, ya que representan un conjunto finito de niveles (dinucleótidos de ADN) en lugar de valores de caracteres arbitrarios.

lvls = c("AA", "AC", "AG", "AT", "CA", "CC", "CG", "CT", "GA", "GC", 
     "GG", "GT", "TA", "TC", "TG", "TT", "ID", "DI", "DD", "II") 
X1 <- factor(c("AC", "AC", "AC", "CA", "TA", "AT", "CC", "CC"), levels=lvls) 
X2 <- factor(c("AC", "AC", "AC", "CA", "AT", "CA", "AC", "TC"), levels=lvls) 
X3 <- factor(c("AC", "AC", "AC", "AC", "AA", "AT", "CC", "CA"), levels=lvls) 
mydf1 <- data.frame(X1, X2, X3) 

Del mismo modo, "11" es un nivel de un factor, y no el número once. Así que una correspondencia entre los niveles es

xlate <- c("AA" = "11", "AC" = "12", "AG" = "13", "AT" = "14", 
      "CA"= "12", "CC" = "22", "CG"= "23","CT"= "24", 
      "GA" = "13", "GC" = "23", "GG"= "33","GT"= "34", 
      "TA"= "14", "TC" = "24", "TG"= "34","TT"="44", 
      "ID"= "56", "DI"= "56", "DD"= "55", "II"= "66") 

y a 'volver a nivelar' una sola variable

levels(X1) <- xlate 

para volver a nivel de todas las columnas de la trama de datos,

as.data.frame(lapply(mydf1, `levels<-`, xlate)) 

Usando sapply no es apropiado, porque eso crea una matriz (de carácter), aunque lo haya llamado outdataframe. La distinción podría ser importante para los datos de SNP que esto podría representar, ya que millones de SNP en 1000 muestras como matriz se implementarían un único vector de longitud más largo que el vector más largo R puede almacenar (se está introduciendo un soporte vectorial de módulo grande en R-devel), mientras que el marco de datos sería una lista de vectores de solo millones de elementos cada uno.