Diese Antwort wird viele der gleichen Elemente wie vorhandene Antworten abdecken, aber dieses Problem (Übergabe von Spaltennamen an Funktionen) tritt häufig genug auf, dass ich wollte, dass es eine Antwort gibt, die die Dinge etwas umfassender behandelt.
Angenommen, wir haben einen sehr einfachen Datenrahmen:
dat <- data.frame(x = 1:4,
y = 5:8)
und wir möchten eine Funktion schreiben, die eine neue Spalte erstellt z
, die die Summe der Spalten x
und ist y
.
Ein sehr häufiger Stolperstein ist, dass ein natürlicher (aber falscher) Versuch oft so aussieht:
foo <- function(df,col_name,col1,col2){
df$col_name <- df$col1 + df$col2
df
}
#Call foo() like this:
foo(dat,z,x,y)
Das Problem hierbei ist, dass df$col1
der Ausdruck nicht ausgewertet wird col1
. Es wird einfach nach einer Spalte df
gesucht, die buchstäblich aufgerufen wird col1
. Dieses Verhalten wird im ?Extract
Abschnitt "Rekursive (listähnliche) Objekte" beschrieben.
Die einfachste und am häufigsten empfohlene Lösung besteht darin, einfach von $
zu zu wechseln [[
und die Funktionsargumente als Zeichenfolgen zu übergeben:
new_column1 <- function(df,col_name,col1,col2){
#Create new column col_name as sum of col1 and col2
df[[col_name]] <- df[[col1]] + df[[col2]]
df
}
> new_column1(dat,"z","x","y")
x y z
1 1 5 6
2 2 6 8
3 3 7 10
4 4 8 12
Dies wird oft als "Best Practice" bezeichnet, da es die Methode ist, die am schwierigsten zu vermasseln ist. Das Übergeben der Spaltennamen als Zeichenfolgen ist so eindeutig wie möglich.
Die folgenden zwei Optionen sind weiter fortgeschritten. Viele beliebte Pakete verwenden diese Art von Techniken, aber ihre gute Verwendung erfordert mehr Sorgfalt und Geschick, da sie subtile Komplexitäten und unerwartete Fehlerquellen mit sich bringen können. Dieser Abschnitt von Hadleys Advanced R-Buch ist eine hervorragende Referenz für einige dieser Probleme.
Wenn Sie den Benutzer wirklich vor der Eingabe all dieser Anführungszeichen bewahren möchten, besteht eine Option möglicherweise darin, nackte, nicht in Anführungszeichen gesetzte Spaltennamen in Zeichenfolgen zu konvertieren, indem Sie Folgendes verwenden deparse(substitute())
:
new_column2 <- function(df,col_name,col1,col2){
col_name <- deparse(substitute(col_name))
col1 <- deparse(substitute(col1))
col2 <- deparse(substitute(col2))
df[[col_name]] <- df[[col1]] + df[[col2]]
df
}
> new_column2(dat,z,x,y)
x y z
1 1 5 6
2 2 6 8
3 3 7 10
4 4 8 12
Das ist, ehrlich gesagt, wahrscheinlich ein bisschen albern, da wir wirklich das Gleiche tun wie in new_column1
, nur mit ein paar zusätzlichen Arbeiten, um nackte Namen in Zeichenfolgen umzuwandeln.
Wenn wir wirklich ausgefallen sein möchten , können wir uns entscheiden, dass wir flexibler sein und andere Kombinationen von zwei Variablen zulassen möchten , anstatt die Namen von zwei hinzuzufügenden Spalten zu übergeben. In diesem Fall würden wir wahrscheinlich eval()
auf einen Ausdruck zurückgreifen, der die beiden Spalten umfasst:
new_column3 <- function(df,col_name,expr){
col_name <- deparse(substitute(col_name))
df[[col_name]] <- eval(substitute(expr),df,parent.frame())
df
}
Nur zum Spaß verwende ich immer noch deparse(substitute())
den Namen der neuen Spalte. Hier funktioniert alles:
> new_column3(dat,z,x+y)
x y z
1 1 5 6
2 2 6 8
3 3 7 10
4 4 8 12
> new_column3(dat,z,x-y)
x y z
1 1 5 -4
2 2 6 -4
3 3 7 -4
4 4 8 -4
> new_column3(dat,z,x*y)
x y z
1 1 5 5
2 2 6 12
3 3 7 21
4 4 8 32
Die kurze Antwort lautet also im Grunde: Übergeben Sie die Spaltennamen von data.frame als Zeichenfolgen und [[
wählen Sie einzelne Spalten aus. Fangen Sie erst an eval
, sich substitute
mit usw. zu beschäftigen, wenn Sie wirklich wissen, was Sie tun.