it-swarm.com.de

Wählen Sie mit Hilfe von $ und einem Vektor von Spaltennamen dynamisch Datenrahmenspalten aus

Ich möchte einen Datenrahmen basierend auf verschiedenen Spalten anordnen. Ich habe einen Zeichenvektor mit den relevanten Spaltennamen, auf dem die order basieren sollte:

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

Ich möchte die Namen in parameter durchlaufen und dynamisch die Spalte auswählen, die für order meiner Daten verwendet werden soll:

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

wobei X1:10 ist (weil ich 10 Elemente in parameter habe).


Um mein Beispiel reproduzierbar zu machen, betrachten Sie den Datensatz mtcars und einige Variablennamen, die in einem Zeichenvektor cols gespeichert sind. Wenn ich versuche, eine Variable aus mtcars mit einer dynamischen Teilmenge von cols auszuwählen, ähnlich wie oben (Q1_R1000$parameter[X]), wird die Spalte nicht ausgewählt: 

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

Mit $ können Sie diese Art von Subsetting nicht durchführen. Im Quellcode (R/src/main/subset.c) heißt es:

/ * Der $ subset-Operator.
Wir müssen sicher sein, nur das erste Argument zu bewerten.
Das zweite ist ein Symbol, das abgeglichen werden muss und nicht ausgewertet werden muss.
* /

Zweites Argument Was?! Sie müssen erkennen, dass $ wie alles andere in R (einschließlich beispielsweise (, +, ^ etc) eine Funktion ist, die Argumente akzeptiert und ausgewertet wird. df$V1 könnte als umgeschrieben werden

`$`(df , V1)

oder in der Tat

`$`(df , "V1")

Aber...

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

... zum Beispiel wird niemals funktionieren, noch wird alles andere, was zuerst im zweiten Argument bewertet werden muss. Sie können nur einen String übergeben, derneverausgewertet wird. 

Verwenden Sie stattdessen [ (oder [[, wenn Sie nur eine einzelne Spalte als Vektor extrahieren möchten). 

Zum Beispiel,

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]

Sie können die Reihenfolge ohne Schleifen durchführen. Verwenden Sie do.call, um den Aufruf von order zu erstellen. Hier ist ein reproduzierbares Beispiel:

#  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
144
Simon O'Hanlon

Wenn ich es richtig verstanden habe, haben Sie einen Vektor mit Variablennamen und möchten jeden Namen durchlaufen und Ihren Datenrahmen danach sortieren. Wenn ja, sollte dieses Beispiel eine Lösung für Sie darstellen. Das Hauptproblem in Ihrem (das vollständige Beispiel ist nicht vollständig, daher bin ich mir nicht sicher, was noch fehlt), dass es order(Q1_R1000[,parameter[X]]) anstelle von order(Q1_R1000$parameter[X]) sein sollte, da es sich bei dem Parameter um ein externes Objekt handelt, das einen Variablennamen enthält, der einem a entgegensteht Direkte Spalte Ihres Datenrahmens (was wann der $ angebracht wäre).

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
3
David

Die Verwendung von dplyr bietet eine einfache Syntax zum Sortieren der Datenrahmen

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

Es kann nützlich sein, die NSE-Version zu verwenden, um das dynamische Erstellen der Sortierliste zu ermöglichen

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

Hatte ein ähnliches Problem aufgrund einiger CSV-Dateien, die verschiedene Namen für dieselbe Spalte hatten.
Dies war die Lösung:

Ich habe eine Funktion geschrieben, um den ersten gültigen Spaltennamen in einer Liste zurückzugeben, und dann ...

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

wenn Sie eine Spalte mit einem bestimmten Namen auswählen möchten, tun Sie dies einfach

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

sie können es auch in einer Schleife ausführen. Umgekehrt, um einen dynamischen Namen hinzuzufügen, z. B. wenn A ein Datenrahmen ist und xyz eine Spalte ist, die als x bezeichnet werden soll, dann mache ich das gerne

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

auch dies kann in einer Schleife hinzugefügt werden

0
Q1_R1000[do.call(order, Q1_R1000[parameter]), ]
0
Hong Ooi