objetos - tablas en r




¿Cómo aplicar funciones en columnas para marcos de datos con diferentes tamaños en la lista anidada? (3)

En R, para aplicar alguna función a una columna, puede hacer:

df$col <- someFunction(df$col)

Ahora mi pregunta es, ¿cómo haces la tarea similar cuando tienes marcos de datos en una lista anidada? Digamos que tengo una lista como esta, donde tengo marcos de datos en el segundo nivel desde la raíz.

                                           +------+------+
                                  type1    | id   | name |
                              +----------->|------|------|
                              |            |      |      |
                              |            |      |      |
                year1         |            +------+------+
           +------------------+
           |                  |
           |                  |            +------+------+-----+
           |                  |  type2     | meta1|meta2 | name|
           |                  +----------> |------|------|-----|
           |                               |      |      |     |
           +                               +------+------+-----+
           |                     type1    +------+------+
           |                  +---------> | id   |name  |
           |                  |           |------|------|
           |     year2        |           |      |      |
   list    +----------------->+           |      |      |
           +                  |           +------+------+
           |                  |  type2     +------+------+-----+
           |                  +--------->  | meta1|meta2 |name |
           |                               |------|------|-----|
           |                               |      |      |     |
           |                    type1      +------+------+-----+
           |                 +---------->  +------+------+
           |                 |             | id   |name  |
           |     year3       |             |------|------|
           +-----------------+             |      |      |
                             |             |      |      |
                             |  type2      +------+------+
                             +---------->  +------+------+-----+
                                           |meta1 | meta2|name |
                                           |------|------|-----|
                                           |      |      |     |
                                           +------+------+-----+

Y quiero modificar la columna "nombre" en cada uno de los marcos de datos en las hojas con algunas funciones y almacenar los resultados allí. ¿Cómo haces eso?

Aquí está el ejemplo de datos:

data<-list()

data$yr2001$type1 <- df_2001_1 <- data.frame(index=1:3,name=c("jack","king","larry"))
data$yr2001$type2 <- df_2001_2 <- data.frame(index=1:5,name=c("man","women","oliver","jack","jill"))
data$yr2002$type1 <- df_2002_1 <- data.frame(index=1:3,name=c("janet","king","larry"))
data$yr2002$type2 <- df_2002_2 <- data.frame(index=1:5,name=c("alboyr","king","larry","rachel","sam"))
data$yr2003$type1 <- df_2003_1 <- data.frame(index=1:3,name=c("dan","jay","zang"))
data$yr2003$type2 <- df_2003_2 <- data.frame(index=1:5,name=c("zang","king","larry","kim","fran"))

Digamos que quiero mayúsculas todos los nombres en la columna de nombre en cada marco de datos almacenado en la lista


Aquí hay una versión realmente recursiva basada en lapply (es decir, que funcionará con anidamiento más profundo) y no hace ninguna otra suposición, excepto que los únicos tipos de hojas de terminal que tiene son marcos de datos. Desafortunadamente, la rapply no detendrá la recursión en data.frames, por lo que tendrá que lapply si desea operar en los marcos de datos (de lo contrario, la respuesta de Matthew es perfecta).

samp.recur <- function(x) 
  lapply(x, 
    function(y) 
      if(is.data.frame(y)) transform(y, name=toupper(name)) else samp.recur(y))

Esto produce:

samp.recur(data)
# $yr2001
# $yr2001$type1
#   index  name
# 1     1  JACK
# 2     2  KING
# 3     3 LARRY

# $yr2001$type2
#   index   name
# 1     1    MAN
# 2     2  WOMEN
# 3     3 OLIVER
# 4     4   JACK
# 5     5   JILL

# etc...

Aunque también estoy de acuerdo con otros, es posible que desee considerar la reestructuración de sus datos.


Estoy de acuerdo con el comentario de @ joran anterior --- esto mendiga que se consolide agregando tipo como columna. Pero aquí hay una manera con la rapply . Esto supone que la columna de name es la única columna de factor en cada data.frame anidado. Como en la respuesta de @ josilber, mi función de elección es toupper .

rapply(data, function(x) toupper(as.character(x)), classes='factor', how='replace')

Esto eliminará la clase data.frame , pero se conserva la estructura esencial. Si sus columnas de nombre ya son character , entonces las usaría.

rapply(data, toupper, classes='character', how='replace')

Puede anidar la función de lapply dos veces para acceder a los marcos de datos internos. Aquí, aplico toupper a cada variable de name :

result <- lapply(data, function(x) {
  lapply(x, function(y) {
    y$name = toupper(y$name)
    return(y)
  })
})
result

# $yr2001
# $yr2001$type1
#   index  name
# 1     1  JACK
# 2     2  KING
# 3     3 LARRY
# 
# $yr2001$type2
#   index   name
# 1     1    MAN
# 2     2  WOMEN
# 3     3 OLIVER
# 4     4   JACK
# 5     5   JILL
# 
# 
# $yr2002
# $yr2002$type1
#   index  name
# 1     1 JANET
# 2     2  KING
# 3     3 LARRY
# 
# $yr2002$type2
#   index   name
# 1     1 ALBOYR
# 2     2   KING
# 3     3  LARRY
# 4     4 RACHEL
# 5     5    SAM
# 
# 
# $yr2003
# $yr2003$type1
#   index name
# 1     1  DAN
# 2     2  JAY
# 3     3 ZANG
# 
# $yr2003$type2
#   index  name
# 1     1  ZANG
# 2     2  KING
# 3     3 LARRY
# 4     4   KIM
# 5     5  FRAN




plyr