Selecionar dinamicamente colunas de frameworks de dados usando $ e um vetor de nomes de coluna

Desejo solicitar um quadro de dados com base em colunas diferentes, uma por vez. Eu tenho um vetor de caractere com os nomes de coluna relevantes em que o order deve ser baseado:

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

Gostaria de fazer um loop sobre os nomes no parameter e selecionar dinamicamente a coluna a ser usada para order meus dados:

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

onde X é 1:10 (porque eu tenho 10 itens no parameter ).


Para tornar meu exemplo reproduzível, considere o dataset mtcars e alguns nomes de variables ​​armazenados em um vetor de caractere cols . Quando tento selecionar uma variável de mtcars usando um subconjunto dynamic de cols , de maneira semelhante à anterior ( Q1_R1000$parameter[X] ), a coluna não está selecionada:

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

Você não pode fazer esse tipo de subconjunto com $ . No código fonte ( R/src/main/subset.c ) afirma:

/ * O operador $ subconjunto.
Precisamos ter certeza de avaliar apenas o primeiro argumento.
O segundo será um símbolo que precisa ser correspondido, não avaliado.
* /

Segundo argumento? O que?! Você tem que perceber que $ , como todo o resto em R, (incluindo por exemplo ( , + , ^ etc) é uma function, que recebe argumentos e é avaliada. df$V1 pode ser reescrito como

 `$`(df , V1) 

ou de fato

 `$`(df , "V1") 

Mas…

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

… por exemplo nunca funcionará, nem qualquer outra coisa que deva primeiro ser avaliada no segundo argumento. Você só pode passar uma string que nunca é avaliada.

Em vez disso, use [ (ou [[ se você quiser extrair apenas uma única coluna como um vetor).

Por exemplo,

 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] 

Você pode executar a ordenação sem loops, usando do.call para construir a chamada à order . Aqui está um exemplo reproduzível abaixo:

 # 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 

Se bem entendi, você tem um vetor contendo nomes de variables ​​e gostaria de percorrer cada nome e classificar seu quadro de dados por eles. Nesse caso, este exemplo deve ilustrar uma solução para você. O problema principal em seu (o exemplo completo não está completo, então não tenho certeza do que mais você pode estar perdendo) é que ele deve ser order(Q1_R1000[,parameter[X]]) vez de order(Q1_R1000$parameter[X]) , já que o parâmetro é um object externo que contém um nome de variável oposto a uma coluna direta do seu quadro de dados (que quando o $ seria apropriado).

 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 

Usando dplyr fornece uma syntax fácil para classificar os frameworks de dados

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

Pode ser útil usar a versão NSE para permitir a construção dinâmica da lista de sorting

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

Teve problema semelhante devido a alguns arquivos CSV que tinham vários nomes para a mesma coluna.
Esta foi a solução:

Eu escrevi uma function para retornar o primeiro nome de coluna válido em uma lista, então usei …

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

Se você quiser selecionar uma coluna com um nome específico, faça

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

você pode executá-lo em loop, assim inverter caminho para adicionar nome dynamic, por exemplo, se A é o quadro de dados e xyz é a coluna a ser nomeada como x, então eu gosto disso

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

novamente isso também pode ser adicionado em loop