R anidado para bucles fusionar marcos de datos

Tengo un marco de datos en el que cada columna es una serie temporal de números (del 0 al 8) que representan diferentes comportamientos durante el cortejo de los animales. Me gustaría comprobar si existe un patrón como que un determinado comportamiento es seguido con mayor frecuencia por otro. He escrito una función que me permite calcular las frecuencias de los comportamientos que siguen a un comportamiento dado después de un intervalo de tiempo particular:

> data[,3]
  [1]  1  1  1  1  7  7  3  3  7  3  1  1  8  1  3  3  3  5  1  1  4 ... 

neighbor <- function(DATA, BEHAVIOR, INTERVAL)
{
total=c(0)
tmp = data.frame(total=c(0:8),Freq=rep(0,9))
number_of_x = which(DATA == BEHAVIOR)

for(i in number_of_x){
              total = append(total,DATA[i+INTERVAL,])
}
tmp = merge(tmp,table(total), by=c("total"), all=T)
tmp[is.na(tmp)] <- 0
subset(tmp, select = ncol(tmp))
}

Así que ejecuto la función para, digamos, la tercera columna, el comportamiento 3 y el siguiente comportamiento en el tiempo (1) y obtengo lo que quiero:

> neighbor(as.data.frame(data[,3], 3, 1]
Freq.y
0 0.01
1 0.71
2 0.01
3 0.21
4 0.01
5 0.04
6 0.01
7 0.02
8 0.00

Ahora me gustaría usar una función similar para obtener las frecuencias de los nueve comportamientos. Algo como:

neighborAll <- function(DATA, INTERVAL)
{
total=c(0)
tmp = data.frame(total=c(0:8),Freq=rep(0,9))
for(a in c(0:8)){
number_of_x = which(DATA == a)
for(i in number_of_x){
      total = c(total,DATA[i+INTERVAL,])
}
tmp=merge(tmp, table(total), by = c("total"), all=T)
tmp[is.na(tmp)] <- 0
}
tmp[,3:9]
}

> neighborAll(as.data.frame(data[,3], 1)

Yo obtengo:

Error in merge.data.frame(tmp, table(total), by = c("total"), all = T) : 
  there is already a column named ‘Freq.x’

Cualquier idea sería bienvenida. Gracias de antemano, José

preguntado el 21 de mayo de 12 a las 19:05

Un ejemplo reproducible recorrerá un largo camino, debo reconocer. -

@lince, si desea respuestas, realmente debería proporcionar un ejemplo reproducible que se pueda copiar y pegar en una sesión R (incluso si falla). Eso puede significar crear una pieza de código más simple con datos ficticios, lo que puede parecer mucho trabajo. Sin embargo, descubrí que preparar una pregunta para stackoverflow es una disciplina útil y varias veces encontré la respuesta yo mismo sin necesidad de publicar la pregunta en SO. El código debe ser conciso; deshacerse de todo lo que no se necesita para entender el problema. ¡Mi pregunta más reciente fue justamente criticada por no tener un ejemplo lo suficientemente mínimo! -

Reescribir es lo mejor; como muestran las respuestas a continuación. Pero el problema anterior podría solucionarse cambiando el nombre de la nueva columna antes de fusionarla, ya que el mensaje de error indica que tiene varias columnas con el mismo nombre, o noto que no toma un subconjunto de columnas en la versión Todo; puede ser que esté cargando más columnas de las que desea cada vez, y tienen el mismo nombre. -

Aaron, tienes razón, si agrego [suffixes=c("", ".x")] puedo deshacerme del mensaje de error. -

2 Respuestas

Esencialmente quieres esto:

neighborAll <- function(DATA, INTERVAL, TABLE)
{
    for(i in 1:(nrow(TABLE) - 1))
    {
        neighbors <- DATA[which(DATA == i) + INTERVAL]
        tab <- table(neighbors)
        TABLE[TABLE$behavior %in% names(tab), i + 2] <- tab
    }
    return(TABLE)
}

x<-c(1, 1, 1, 1, 7, 7, 3, 3, 7, 3, 1, 1 ,8, 1, 3, 3, 3, 5, 1, 1, 4)

behavior <- 0:8
n <- length(behavior)
tmp <- matrix(nrow=n, ncol=n)
colnames(tmp) <- paste("freq", behavior, sep="")
freqtab <- data.frame(behavior, tmp)

neighborAll(x, 1, freqtab)

contestado el 22 de mayo de 12 a las 14:05

Si no fuera por acertar con los nombres, cada uno de estos podría ser ingenioso.

neighbor <- function(DATA, BEHAVIOR, INTERVAL) {
  nbins <- 1+max(0, DATA, na.rm = TRUE)
  out <- tabulate(1+DATA[which(DATA==BEHAVIOR)+INTERVAL], nbins=nbins)
  names(out) <- 1:nbins - 1
  out
}

neighborAll <- function(DATA, INTERVAL) {
  out <- sapply(0:max(DATA, na.rm=TRUE), 
         function(BEHAVIOR) neighbor(DATA, BEHAVIOR, INTERVAL))
  colnames(out) <- 0:max(DATA, na.rm=TRUE)
  out
}

> x <- c(1, 1, 1, 1, 7, 7, 3, 3, 7, 3, 1, 1 ,8, 1, 3, 3, 3, 5, 1, 1, 4)

> neighbor(x,3,1)
0 1 2 3 4 5 6 7 8 
0 1 0 3 0 1 0 1 0 

> neighborAll(x,1)
  0 1 2 3 4 5 6 7 8
0 0 0 0 0 0 0 0 0 0
1 0 5 0 1 0 1 0 0 1
2 0 0 0 0 0 0 0 0 0
3 0 1 0 3 0 0 0 2 0
4 0 1 0 0 0 0 0 0 0
5 0 0 0 1 0 0 0 0 0
6 0 0 0 0 0 0 0 0 0
7 0 1 0 1 0 0 0 1 0
8 0 1 0 0 0 0 0 0 0

contestado el 23 de mayo de 12 a las 12:05

Gracias Aaron, tu solución es clara, simple y muy elegante. Solo agregué na.rm = TRUE en max(DATA) de la segunda función. Este foro es realmente útil y estoy aprendiendo mucho de todos ustedes. - idioma

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.