Seleccione dinámicamente las columnas de marcos de datos usando $ y un valor de carácter

Tengo un vector de diferentes nombres de columnas y quiero ser capaz de bucle sobre cada uno de ellos para extraer esa columna de un marco de datos. Por ejemplo, considere el conjunto de datos mtcars y algunos nombres variables almacenados en un vector de carácter cols. Cuando intento seleccionar una variable desde mtcars usando un subconjunto dinámico cols, ni siquiera de estos trabajos

cols <- c("mpg", "cyl", "am")
col <- cols[1]
col
# [1] "mpg"

mtcars$col
# NULL
mtcars$cols[1]
# NULL

cómo puedo conseguir que estos devuelvan los mismos valores

mtcars$mpg

Además, ¿cómo puedo buclear todas las columnas en cols para conseguir los valores en algún tipo de bucle.

for(x in seq_along(cols)) {
   value <- mtcars[ order(mtcars$cols[x]), ]
}

Pregunta hecha hace 10 años, 6 meses, 14 días - Por pixelpioneerc4b5


11 Respuestas:

  • No puedes hacer ese tipo de subsetting con $. En el código fuente (R/src/main/subset.cDice:

    /*El subconjunto de $ operador.
    Tenemos que estar seguros de evaluar el primer argumento.
    El segundo será un símbolo que necesita ser igualado, no evaluado.
    */

    ¿El segundo argumento? ¿Qué? Tienes que darte cuenta de que $, como todo lo demás en R, (incluyendo por ejemplo ( , + , ^ etc) es una función, que toma argumentos y se evalúa. df$V1 podría ser reescrito como

    `$`(df , V1)
    

    o de hecho

    `$`(df , "V1")
    

    Pero...

    `$`(df , paste0("V1") )
    

    ...por ejemplo, nunca funcionará, ni nada más que primero debe ser evaluado en el segundo argumento. Sólo puede pasar una cuerda que es nunca jamás nunca jamás nunca jamás nunca jamás nunca jamás jamás nunca jamás nunca jamás nunca jamás nunca jamás jamás nunca jamás nunca jamás nunca jamás nunca jamás nunca jamás nunca jamás nunca jamás nunca jamás jamás nunca jamás jamás nunca jamás nunca jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás jamás evaluado.

    En lugar de utilizar [ (o [[ si quieres extraer sólo una sola columna como vector).

    Por ejemplo,

    var <- "mpg"
    #Doesn't work
    mtcars$var
    #These both work, but note that what they return is different
    # the first is a vector, the second is a data.frame
    mtcars[[var]]
    mtcars[var]
    

    Puede realizar el pedido sin bucles, utilizando do.call para construir la llamada order. Aquí hay un ejemplo reproducible a continuación:

    #  set seed for reproducibility
    set.seed(123)
    df <- data.frame( col1 = sample(5,10,repl=T) , col2 = sample(5,10,repl=T) , col3 = sample(5,10,repl=T) )
    
    #  We want to sort by 'col3' then by 'col1'
    sort_list <- c("col3","col1")
    
    #  Use 'do.call' to call order. Seccond argument in do.call is a list of arguments
    #  to pass to the first argument, in this case 'order'.
    #  Since  a data.frame is really a list, we just subset the data.frame
    #  according to the columns we want to sort in, in that order
    df[ do.call( order , df[ , match( sort_list , names(df) ) ]  ) , ]
    
       col1 col2 col3
    10    3    5    1
    9     3    2    2
    7     3    2    3
    8     5    1    3
    6     1    5    4
    3     3    4    4
    2     4    3    4
    5     5    1    4
    1     2    5    5
    4     5    3    5
    

    Respondida el Aug 14, 2013 a las 02:37 - por debugdynamo

    Votos positivos: 0 | Votos negativos: 0

  • Utilizando dplyr proporciona una sintaxis fácil para ordenar los marcos de datos

    library(dplyr)
    mtcars %>% arrange(gear, desc(mpg))
    

    Puede ser útil utilizar la versión NSE como se muestra aquí para permitir la construcción dinámica de la lista de tipos

    sort_list <- c("gear", "desc(mpg)")
    mtcars %>% arrange_(.dots = sort_list)
    

    Respondida el Aug 14, 2013 a las 02:42 - por bytebuster

    Votos positivos: 0 | Votos negativos: 0

  • Si lo entiendo correctamente, usted tiene un vector que contiene nombres variables y le gustaría bucle a través de cada nombre y ordenar su marco de datos por ellos. Si es así, este ejemplo debe ilustrar una solución para usted. El tema principal en el suyo (el ejemplo completo no está completo así que no estoy seguro de qué más puede estar desaparecido) es que debe ser order(Q1_R1000[,parameter[X]]) en lugar de order(Q1_R1000$parameter[X]), ya que el parámetro es un objeto externo que contiene un nombre variable opuesto a una columna directa de su marco de datos (que cuando el $ sería apropiado).

    set.seed(1)
    dat <- data.frame(var1=round(rnorm(10)),
                       var2=round(rnorm(10)),
                       var3=round(rnorm(10)))
    param <- paste0("var",1:3)
    dat
    #   var1 var2 var3
    #1    -1    2    1
    #2     0    0    1
    #3    -1   -1    0
    #4     2   -2   -2
    #5     0    1    1
    #6    -1    0    0
    #7     0    0    0
    #8     1    1   -1
    #9     1    1    0
    #10    0    1    0
    
    for(p in rev(param)){
       dat <- dat[order(dat[,p]),]
     }
    dat
    #   var1 var2 var3
    #3    -1   -1    0
    #6    -1    0    0
    #1    -1    2    1
    #7     0    0    0
    #2     0    0    1
    #10    0    1    0
    #5     0    1    1
    #8     1    1   -1
    #9     1    1    0
    #4     2   -2   -2
    

    Respondida el Aug 14, 2013 a las 02:51 - por webweaverx

    Votos positivos: 0 | Votos negativos: 0

  • I would implement the sym función rlang paquete. Digamos el col tiene valor "mpg". La idea es subponerla.

    mtcars %>% pull(!!sym(col))
    #  [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7 15.0
    # [32] 21.4
    

    ¡Sigue Coding!

    Respondida el Aug 14, 2013 a las 02:59 - por debugdragon

    Votos positivos: 0 | Votos negativos: 0

  • Otra solución es usar #get:

    > cols <- c("cyl", "am")
    > get(cols[1], mtcars)
     [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
    

    Respondida el Aug 14, 2013 a las 03:06 - por quantumcoderd26d

    Votos positivos: 0 | Votos negativos: 0

  • Tenía un problema similar debido a algunos archivos CSV que tenían varios nombres para la misma columna.
    Esta fue la solución:

    Escribí una función para devolver el primer nombre de columna válido en una lista, y luego usé eso...

    # Return the string name of the first name in names that is a column name in tbl
    # else null
    ChooseCorrectColumnName <- function(tbl, names) {
    for(n in names) {
        if (n %in% colnames(tbl)) {
            return(n)
        }
    }
    return(null)
    }
    
    then...
    
    cptcodefieldname = ChooseCorrectColumnName(file, c("CPT", "CPT.Code"))
    icdcodefieldname = ChooseCorrectColumnName(file, c("ICD.10.CM.Code", "ICD10.Code"))
    
    if (is.null(cptcodefieldname) || is.null(icdcodefieldname)) {
            print("Bad file column name")
    }
    
    # Here we use the hash table implementation where 
    # we have a string key and list value so we need actual strings,
    # not Factors
    file[cptcodefieldname] = as.character(file[cptcodefieldname])
    file[icdcodefieldname] = as.character(file[icdcodefieldname])
    for (i in 1:length(file[cptcodefieldname])) {
        cpt_valid_icds[file[cptcodefieldname][i]] <<- unique(c(cpt_valid_icds[[file[cptcodefieldname][i]]], file[icdcodefieldname][i]))
    }
    

    Respondida el Aug 14, 2013 a las 03:15 - por codemaestro

    Votos positivos: 0 | Votos negativos: 0

  • mtcars[do.call(order, mtcars[cols]), ]
    

    Respondida el Aug 14, 2013 a las 03:21 - por cyberscribe

    Votos positivos: 0 | Votos negativos: 0

  • Me pasó varias veces. Use el paquete Data.table. Cuando sólo tienes una columna a la que debes referirte. Usar

    DT[[x]]
    

    o

    DT[,..x]
    

    Cuando tenga 2 o más columnas para referirse, asegúrese de utilizar:

    DT[,..x]
    

    Ese x puede ser cadenas en otros datos. marco.

    Respondida el Aug 14, 2013 a las 03:31 - por csharpsorcerer

    Votos positivos: 0 | Votos negativos: 0

  • demasiado tarde... pero creo que tengo la respuesta...

    Aquí está mi estudio de muestra. df dataframe -

       >study.df
       study   sample       collection_dt other_column
       1 DS-111 ES768098 2019-01-21:04:00:30         
       2 DS-111 ES768099 2018-12-20:08:00:30   some_value
       3 DS-111 ES768100                   some_value
    

    Y luego...

    > ## Selecting Columns in an Given order
    > ## Create ColNames vector as per your Preference
    > 
    > selectCols <- c('study','collection_dt','sample')
    > 
    > ## Select data from Study.df with help of selection vector
    > selectCols %>% select(.data=study.df,.)
       study       collection_dt   sample
    1 DS-111 2019-01-21:04:00:30 ES768098
    2 DS-111 2018-12-20:08:00:30 ES768099
    3 DS-111                 ES768100
    > 
    

    Respondida el Aug 14, 2013 a las 03:39 - por webweaverx

    Votos positivos: 0 | Votos negativos: 0

  • Cuando utilizas el operador $ para seleccionar columnas de un marco de datos en R, necesitas utilizar la sintaxis correcta para seleccionar columnas de manera dinámica. En lugar de mtcars$col, que no funcionará porque R buscará una columna llamada col, puedes utilizar el operador de doble corchete [[]] para seleccionar columnas dinámicamente.

    Aquí te muestro cómo puedes seleccionar dinámicamente columnas de un marco de datos usando un vector de nombres de columnas:

    R
    

    Vector de nombres de columnas

    cols <- c("mpg", "cyl", "am")

    Ejemplo de cómo seleccionar una columna de manera dinámica

    col <- cols[1] mtcars[[col]]

    Bucle para obtener los valores de cada columna en cols

    for(col in cols) { value <- mtcars[[col]] print(value) }

    La clave está en usar [[col]] en lugar de $col para seleccionar dinámicamente las columnas. De esta forma, podrás acceder a las columnas de manera dinámica y recorrer

    Respondida el Aug 15, 2013 a las 02:34 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Cómo seleccionar dinámicamente las columnas de marcos de datos usando $ y un valor de carácter:*

    Para seleccionar dinámicamente una columna de un marco de datos utilizando el operador $ y un valor de carácter, primero debes encerrar el valor del carácter entre comillas simples (') o comillas dobles ("). Por ejemplo:

    
    mtcars$'mpg'
    mtcars["mpg"]
    

    Cómo obtener los valores en un bucle:

    Para obtener los valores de todas las variables especificadas en el vector cols usando un bucle, puedes usar el siguiente código:

    
    for (col in cols) {
      value <- mtcars[, col]
    }
    

    Esta versión corregida de tu código debería funcionar:

    
    for(x in seq_along(cols)) {
      value <- mtcars[, cols[x]]
    }
    

    Nota:

    El uso de $ requiere que el nombre de la columna esté entre comillas simples o comillas dobles. * El uso de [ requiere que el nombre de la columna esté entre comas simples o comillas dobles, o entre corchetes ([ ]) si contiene caracteres especiales.

    Respondida el Aug 15, 2013 a las 02:44 - por Gemini

    Votos positivos: 0 | Votos negativos: 0