Seleccione dinámicamente columnas de marcos de datos usando $ y un vector de nombres de columnas

Deseo pedir un dataframe basado en diferentes columnas, una por turno. Tengo un vector de caracteres con los nombres de columna relevantes en los que debe basarse el order :

 parameter <- c("market_value_LOCAL", "ep", "book_price", "sales_price", "dividend_yield", "beta", "TOTAL_RATING_SCORE", "ENVIRONMENT", "SOCIAL", "GOVERNANCE") 

Deseo recorrer los nombres en el parameter y seleccionar dinámicamente la columna que se utilizará para order mis datos:

 Q1_R1000_parameter <- Q1_R1000[order(Q1_R1000$parameter[X]), ] 

donde X es 1:10 (porque tengo 10 elementos en el parameter ).


Para que mi ejemplo sea reproducible, considere el conjunto de datos mtcars y algunos nombres de variables almacenados en un vector de caracteres cols . Cuando bash seleccionar una variable de mtcars utilizando un subconjunto dynamic de cols , de forma similar a la anterior ( Q1_R1000$parameter[X] ), la columna no se selecciona:

 cols <- c("cyl", "am") mtcars$cols[1] # NULL 

No puedes hacer ese tipo de subconjunto con $ . En el código fuente ( R/src/main/subset.c ) declara:

/ * El operador del subconjunto $.
Necesitamos asegurarnos de solo evaluar el primer argumento.
El segundo será un símbolo que debe ser igualado, no evaluado.
* /

Segundo argumento? ¡¿Qué?! Debes 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 reescribirse como

 `$`(df , V1) 

o de hecho

 `$`(df , "V1") 

Pero…

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

… por ejemplo, nunca funcionará, ni ninguna otra cosa que primero deba evaluarse en el segundo argumento. Solo puede pasar una cadena que nunca se evalúa.

En su lugar, use [ (o [[ si desea extraer solo una 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 a 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 

Si entiendo correctamente, tiene un vector que contiene nombres de variables y le gustaría recorrer cada nombre y ordenar su dataframe. Si es así, este ejemplo debería ilustrar una solución para usted. El problema principal en el suyo (el ejemplo completo no está completo, así que no estoy seguro de qué otra cosa puede faltar) es que debe ser order(Q1_R1000[,parameter[X]]) lugar de order(Q1_R1000$parameter[X]) , ya que el parámetro es un objeto externo que contiene un nombre de variable opuesto a una columna directa de su dataframe (que cuando $ 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 

El uso de dplyr proporciona una syntax fácil para clasificar los marcos de datos

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

Puede ser útil usar la versión de NSE para permitir la construcción dinámica de la lista de clasificación

 sort_list <- c("gear", "desc(mpg)") mtcars %>% arrange_(.dots = sort_list) 
 Q1_R1000[do.call(order, Q1_R1000[parameter]), ] 

Tuve 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])) } 

si desea seleccionar una columna con un nombre específico, simplemente haga

 A=mtcars[,which(conames(mtcars)==cols[1])] #and then colnames(mtcars)[A]=cols[1] 

Puede ejecutarlo en bucle así como en forma inversa para agregar un nombre dynamic, por ejemplo, si A es un dataframe y xyz es la columna que se llamará x entonces me gusta esto.

 A$tmp=xyz colnames(A)[colnames(A)=="tmp"]=x 

de nuevo, esto también se puede agregar en bucle