R Apply () -Funktion auf bestimmte Datenrahmenspalten

75

Ich möchte die Apply-Funktion für einen Datenrahmen verwenden, aber die Funktion nur auf die letzten 5 Spalten anwenden.

B<- by(wifi,(wifi$Room),FUN=function(y){apply(y, 2, A)})

Dies gilt A für alle Spalten von y

B<- by(wifi,(wifi$Room),FUN=function(y){apply(y[4:9], 2, A)})

Dies gilt A nur für die Spalten 4-9 von y, aber die Gesamtrendite von B entfernt die ersten 3 Spalten ... Ich möchte diese immer noch, ich möchte nur nicht, dass A auf sie angewendet wird.

wifi[,1:3]+B 

macht auch nicht was ich erwartet / wollte.

skmathur
quelle
2
Der 'by'-Aufruf erschwert diese Frage. Wenn es relevant ist, sollten Sie die Frage umschreiben, um zu klären (was ist WiFi $ Room?). Ich habe in meiner Antwort unten ignoriert.
Leif
Sie könnten cbind(y[1:3], ...)zu dem Ergebnis kommen, das Sie erhalten.
IRTFM

Antworten:

59

Verwenden eines Beispiels data.frame und einer Beispielfunktion (nur +1 für alle Werte)

A <- function(x) x + 1
wifi <- data.frame(replicate(9,1:4))
wifi

#  X1 X2 X3 X4 X5 X6 X7 X8 X9
#1  1  1  1  1  1  1  1  1  1
#2  2  2  2  2  2  2  2  2  2
#3  3  3  3  3  3  3  3  3  3
#4  4  4  4  4  4  4  4  4  4

data.frame(wifi[1:3], apply(wifi[4:9],2, A) )
#or
cbind(wifi[1:3], apply(wifi[4:9],2, A) )

#  X1 X2 X3 X4 X5 X6 X7 X8 X9
#1  1  1  1  2  2  2  2  2  2
#2  2  2  2  3  3  3  3  3  3
#3  3  3  3  4  4  4  4  4  4
#4  4  4  4  5  5  5  5  5  5

Oder auch:

data.frame(wifi[1:3], lapply(wifi[4:9], A) )
#or
cbind(wifi[1:3], lapply(wifi[4:9], A) )

#  X1 X2 X3 X4 X5 X6 X7 X8 X9
#1  1  1  1  2  2  2  2  2  2
#2  2  2  2  3  3  3  3  3  3
#3  3  3  3  4  4  4  4  4  4
#4  4  4  4  5  5  5  5  5  5
die E-Mail
quelle
Gibt es eine Möglichkeit, $eine bestimmte Spalte nach Namen [ : ]zu indizieren, anstatt sie nach Spaltennummer zu indizieren? Ich habe versucht, Spaltennamen hinzuzufügen. Es wurde colnames(wifi) = c("a", "b", "c", "d", "e", "f", "g", "h" ,"i")jedoch kein Versuch unternommen, lapply (wifi $ e, 2, X) zu verwenden.
santeko
9
@skotturi - Sie können dies tun, wifi[c("a","b","c")]um mehrere Spalten nach Namen zu indizieren.
E-Mail
@ thelatemail, In apply(wifi[4:9],2, A), wifi[4:9]is data.frame.Und applykann nur zum Array oder zur Matrix verwendet werden. Warum funktioniert Ihre Antwort?
Kittygirl
@kittygirl - , die da ist anwenden kann auf einem data.frame verwendet werden. Der data.frame wird als Teil der Funktion in eine Matrix gezwungen, wenn apply verwendet wird.
E-Mail
@ thelatemail, werden Informationen zu Rowname oder Colname verloren gehen?
Kittygirl
87

lapplyist wahrscheinlich eine bessere Wahl als applyhier, da durch Anwenden zuerst Ihr data.frame auf ein Array gezwungen wird, was bedeutet, dass alle Spalten denselben Typ haben müssen. Abhängig von Ihrem Kontext kann dies unbeabsichtigte Folgen haben.

Das Muster ist:

df[cols] <- lapply(df[cols], FUN)

Der 'cols'-Vektor kann Variablennamen oder Indizes sein. Ich bevorzuge es, wenn immer möglich, Namen zu verwenden (es ist robust gegenüber Neuanordnungen von Spalten). In Ihrem Fall könnte dies also sein:

wifi[4:9] <- lapply(wifi[4:9], A)

Ein Beispiel für die Verwendung von Spaltennamen:

wifi <- data.frame(A=1:4, B=runif(4), C=5:8)
wifi[c("B", "C")] <- lapply(wifi[c("B", "C")], function(x) -1 * x)
leif
quelle
2
Eine kleine Korrektur: wifi <- data.frame (A = 1: 4, B = runif (4), C = 5: 8)
jcfaria
Könnten Sie genauer angeben, wie Sie den Vektor [cols] erstellt haben?
Mox
@Mox können Sie nur tuncols <- c("var1", "var2")
cparmstrong
als Alternative mit dplyr die Redundanz zu vermeiden , die Spaltenangabe zu wiederholen, könnten Sie tunwifi[4:9] %<>% map_dbl(A)
Agile Bean
1

Wie bereits erwähnt, möchten Sie einfach die Standard-R- applyFunktion auf Spalten ( MARGIN=2) anwenden :

wifi[,4:9] <- apply(wifi[,4:9], MARGIN=2, FUN=A)

Oder kurz:

wifi[,4:9] <- apply(wifi[,4:9], 2, A)

Dadurch werden die Spalten 4: 9 mithilfe der A()Funktion direkt aktualisiert . Nehmen wir nun an, dass dies na.rmein Argument ist A(), für das es wahrscheinlich sein sollte. Wir können übergeben na.rm=T, um NA-Werte wie folgt aus der Berechnung zu entfernen:

wifi[,4:9] <- apply(wifi[,4:9], MARGIN=2, FUN=A, na.rm=T)

Gleiches gilt für alle anderen Argumente, die Sie an Ihre benutzerdefinierte Funktion übergeben möchten.

Adam Erickson
quelle
0

Ich denke, was Sie wollen, ist mapply. Sie können die Funktion auf alle Spalten anwenden und dann einfach die Spalten löschen, die Sie nicht möchten. Wenn Sie jedoch unterschiedliche Funktionen auf unterschiedliche Spalten anwenden, ist es wahrscheinlich, dass Sie eine Mutation aus dem dplyr-Paket wünschen.

Mox
quelle