Skip to content

[R-es] Error en loop anidado con data.table

3 messages · Carlos Ortega, Rodrigo López Correa

#
Hola tengo una tabla de tipo data.frame "datos" con la siguiente
estructura, simplificada en número de niveles por variable, para crear un
ejemplo más sencillo:

id anio t_8a t_10a t_12a rankf8 rankf10 rankf12
1 1 100 220 220 NA NA NA
2 1 140 350 350 NA NA NA
3 2 55 165 165 NA NA NA
4 2 60 200 200 NA NA NA
5 2 100 NA NA NA NA NA
6 3 NA 350 350 NA NA NA

También tengo una matriz, "mat" con la siguiente estructura:

  t_8a t_10a t_12a
1  100   200   200
2   50   150   150
3   NA   250   250



La columna rankf8 la quiero rellenar tomando como referencia valores de
t_8a en "datos" en relación al valor de t_8a en la matriz "mat" y según el
año que le corresponda (1, 2 o 3).

Del mismo modo quiero rellenar los valores de rankf10 y rankf12 pero
tomando como referencia valores de t_10a en "datos" en relación al valor de
t_10a en la matriz "mat" y valores de t_12a en "datos" en relación al valor
de t_12a en la matriz "mat, y según el año que le corresponda (1, 2 o 3).

*Mi objetivo es que quede la tabla "datos" con las columnas rankf8, rankf10
y rankf12 completas según la condición del script:*

id anio t_8a t_10a t_12a rankf8 rankf10 rankf12
1 1 100 220 220 1 1 1
2 1 140 350 350 2 3 3
3 2 55 165 165 1 1 1
4 2 60 200 200 2 2 2
5 2 100 NA NA 3 4 4
6 3 NA 350 350 NA 2 2



*Mi script es el siguiente:*

datos<-data.frame(cbind(id,anireg_cod,t_8a,t_10a,t_12a,rankf8,rankf10,rankf12))

datos<-data.table((datos),key="anireg_cod")

datos[order(anireg_cod,decreasing=FALSE),]

anio<-sort((unique(datos$anireg_cod)))

tiempo<-as.character(c("t_8a","t_10a","t_12a"))


mat<-matrix(c(100,50,NA,200,150,250,200,150,250),3,3)
colnames(mat)<-tiempo
rownames(mat)<-seq(1:length(sort(unique(datos$anireg_cod))))

anio<-sort((unique(datos$anireg_cod)))


rank<-as.character(c("rankf8","rankf10","rankf12"))

for (k in 1:nrow(datos)){

  #recorre variable anio

  for (i in anio){

    for(j in tiempo){

      for(l in rank){

        ifelse(i==datos$anireg_cod & j %in% colnames(datos) &
(datos[k,l==colnames(datos)]

               <=mat[i==rownames(mat)
               ,j==colnames(mat)]*0.1 +
mat[i==rownames(mat),j==colnames(mat)]),
               datos[k,l %in% colnames(datos)]<-1,

               ifelse(i==datos$anireg_cod & j %in% colnames(datos) &
(datos[k,l %in% colnames(datos)]>
                        mat[i==rownames(mat),j==colnames(mat)]*0.1 +
               mat[i==rownames(mat),j==colnames(mat)] &
(i==datos$anireg_cod & j %in% colnames(datos) & (datos[k,l %in%
colnames(datos)])))<=

mat[i==rownames(mat), j==colnames(mat)]*0.5 + mat[i==rownames(mat),
j==colnames(mat)],
               datos[k,l %in% colnames(datos)]<-2,

                ifelse(i==datos$anireg_cod & j %in% colnames(datos) &
(datos[k,l %in% colnames(datos)] & !is.na(datos[k,l %in% colnames(datos)])
mat[i==rownames(mat),j==colnames(mat)]*0.5),
                          datos[k,l %in% colnames(datos)] <-3, 4)))
                   }
    }

  }


}


*El error que se genera es:*

Error in `[<-.data.table`(`*tmp*`, k, l %in% colnames(datos), value = 1) :

  j must be vector of column name or positions



In addition: Warning message:

In i == datos$anireg_cod & j %in% colnames(datos) & (datos[k, l ==  :

  longer object length is not a multiple of shorter object length



Muchas gracias y disculpas si quedó muy largo pero quería explicitar eel
problema lo mejor posible.



Saludos,

Rodrigo.
#
Hola,

Por entender el problema:

id anio t_8a t_10a t_12a rankf8 rankf10 rankf12
1 1 100 220 220 *1* *1 1*
2 1 140 350 350 2 3 3
3 2 55 165 165 1 1 1
4 2 60 200 200 2 2 2
5 2 100 NA NA 3 4 4
6 3 NA 350 350 NA 2 2


   - Entiendo bien que el "1" de rankf8 (en negrita negro) corresponde al
   100 de t_8a que está en la primera fila de t_8a de la matriz pequeña
   - ¿Pero el "1" de rankf10 (negrita rojo) ?. La primera fila de t_10a en
   la matriz pequeña no es un 220 si no un 200.
   - Y algo parecido para el "1" de rankf12 (negrita azul). Hay que buscar
   un 220 en t_12a de la matriz pequeña... ¡Y no está en la primera fila!...

-------Matriz Pequeña-----
  t_8a t_10a t_12a
1  100   200   200
2   50   150   150
3   NA   250   250

Con estas dudas no termino de entender la lógica a aplicar.


Gracias,
Carlos Ortega
www.qualityexcellence.es


El 19 de enero de 2017, 21:29, Rodrigo López Correa <rod99hare en gmail.com>
escribió:

  
    
#
Hola Carlos, primero gracias por contestar.



Disculpas por no haber sido del todo claro. El objetivo es completar las
columnas rankf8, rankf10 y rankf12 según el siguiente criterio:

·         *El valor a asignar a rankf8*, va a depender de la *diferencia
entre el valor de t_8a en ?datos? y el valor de t_8a en ?mat?*.



·         *El valor a asignar a rankf10*, va a depender de la *diferencia
entre el valor de t_10a en ?datos? y el valor de t_10a en ?mat?*.



·         *El valor a asignar a rankf12*, va a depender de la *diferencia
entre el valor de t_12a en ?datos? y el valor de t_12a en ?mat?*.



Los valores a asignar para cada columna rankf  también van a depender del
valor en cada año que debe ser el mismo al comparar los valores en
?datos?como para los valores en ?mat?.


Por ejemplo: columna rankf8.



1)      Si t_8a en ?datos? *<=* al valor en t_8a en ?mat? + 10% del valor
en t_8a en ?mat?: asigna 1 a rankf8.



2)      Si t_8ª en ?datos? *>* t_8a en ?mat? + 10% de t_8a en ?mat? y *<=*
t_8a en ?mat? + 50% de t_8a en ?mat?: asigna 2 a rankf8.





3)      Si t_8ª en ?datos? *>* t_8a en ?mat? + 50% de t_8a en ?mat? y t_8a
en ?mat?es diferente de NA: asigna 3 a rankf8.



4)      Si no se cumplen esas condiciones: asigna 4 a rankf8.



Similares criterios debo seguir para asignar valores a rankf10 y rankf12,
pero las referencias son los valores de t_10a en ?datos? y ?mat? para
rankf10 y los valores de t_12a en ?datos? y ?mat?.



*Ante tus preguntas:*

·  Entiendo bien que el "1" de rankf8 (en negrita negro) corresponde al 100
de t_8a que está en la primera fila de t_8a de la matriz pequeña

Es correcto.


El valor de t_8a en ?datos? para el *año 1*, es 100.


El valor de t_8a en  ?mat? para el *año 1*, es 100.


En este caso t_8a en ?datos? es <= suma de 100 (t_8a en ?mat?) + 100(t_8a
en ?mat?) *0.1.


Por tanto asigno a rankf8, 1.



·  ¿Pero el "1" de rankf10 (negrita rojo) ?. La primera fila de t_10a en la
matriz pequeña no es un 220 si no un 200.

               El valor de t_10a en ?datos? para el *año 1*, es 220.

               El valor de t_10a en  ?mat? para el* año 1, *es 200.

               En este caso t_10a en ?datos? es <= suma de 200 (t_10a en
?mat?) + 200(t_10a en ?mat?) *0.1.

               Por tanto asigno a rankf10, 1.


·  Y algo parecido para el "1" de rankf12 (negrita azul). Hay que buscar un
220 en t_12a de la matriz pequeña... ¡Y no está en la primera fila!.

              El valor de t_12a en ?datos? para el *año 1*, es 220.

              El valor de t_12a en  ?mat? para el* año 1, *es 200.

              En este caso t_12a en ?datos? es <= suma de 200 (t_12a en
?mat?) + 200(t_12a en ?mat?) *0.1.

              Por tanto asigno a rankf12, 1.



Espero haber sido un poco más claro ahora. ¡Muchas gracias!

Rodrigo.





El 20 de enero de 2017, 11:12, Carlos Ortega <cof en qualityexcellence.es>
escribió: