Mutieren Sie mehrere Spalten in einem dataframe
Ich habe einen Datensatz, der wie folgt aussieht.
bankname bankid year totass cash bond loans
Bank A 1 1881 244789 7250 20218 29513
Bank B 2 1881 195755 10243 185151 2800
Bank C 3 1881 107736 13357 177612 NA
Bank D 4 1881 170600 35000 20000 5000
Bank E 5 1881 3200000 351266 314012 NA
und ich will berechnen Sie einige Kennzahlen, basierend auf der Bilanz der Banken. und ich möchte das dataset wie folgt Aussehen
bankname bankid year totass cash bond loans CashtoAsset BondtoAsset LoanstoAsset
Bank A 1 1881 2447890 7250 202100 951300 0.002 0.082 0.388
Bank B 2 1881 195755 10243 185151 2800 0.052 0.945 0.014
Bank C 3 1881 107736 13357 177612 NA 0.123 1.648585431 NA
Bank D 4 1881 170600 35000 20000 5000 0.205 0.117 0.029
Bank E 5 1881 32000000 351266 314012 NA 0.0109 0.009 NA
Hier ist der code, der die Replikation von Daten
bankname <- c("Bank A","Bank B","Bank C","Bank D","Bank E")
bankid <- c( 1, 2, 3, 4, 5)
year<- c( 1881, 1881, 1881, 1881, 1881)
totass <- c(244789, 195755, 107736, 170600, 32000000)
cash<-c(7250,10243,13357,35000,351266)
bond<-c(20218,185151,177612,20000,314012)
loans<-c(29513,2800,NA,5000,NA)
bankdata<-data.frame(bankname, bankid,year,totass, cash, bond, loans)
Zuerst entledigte ich mich der NAs in den Bilanzen.
cols <- c("totass", "cash", "bond", "loans")
bankdata[cols][is.na(bankdata[cols])] <- 0
Dann berechne ich Verhältnisse
library(dplyr)
bankdata<-mutate(bankdata,CashtoAsset = cash/totass)
bankdata<-mutate(bankdata,BondtoAsset = bond/totass)
bankdata<-mutate(bankdata,loanstoAsset =loans/totass)
Aber, statt-computing-alle diese Verhältnisse sind Zeile für Zeile, ich will einen look kreieren, um dies zu tun, alles auf einmal. In Stata, die ich tun würde,
foreach x of varlist cash bond loans {
by bankid: gen `x'toAsset = `x'/totass
}
Wie kann ich dies tun?
- Meta-Kommentare: Beim übersetzen von einer Sprache zur anderen, Sie brauchen nicht zu wörtlich. Schleifen in Stata arbeiten oft besser als array-basierten Berechnungen im R. (Auch das Gegenteil wahr sein kann: die Neulinge Stata aus anderen Sprachen, die oft versuchen, die Schleifen über Beobachtungen, die nur selten benötigt werden.)
- Ich vereinfachen meine Variablen hier, aber in meinem dataset habe ich über 20 Kategorien von Vermögenswerten, so dass eine Schleife ist hilfreich.
- Ich habe nichts gegen Schleifen; ähnlich wie die typischen R-Nutzer wird sicherlich glücklich mit 20 Spalten....
- Wie immer, ich Danke Ihnen für Ihre Hilfe. Ich Lerne viel von Ihnen.
- Vielen Dank für das lassen mich wissen. Das mache ich ab jetzt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Update (wie von den 18ten März, 2019)
Gab es eine änderung. Wir haben mit
funs()
im.funs
(funs(name = f(.)
). Aber dies wird geändert (dplyr 0.8.0 oben). Stattfuns
, jetzt haben wirlist
(list(name = ~f(.))
). Siehe folgende neue Beispiele.Update (ab dem 2. Dezember, 2017)
Da ich auf diese Frage geantwortet haben, habe ich gemerkt, dass SO einige Benutzer haben überprüft diese Antwort. Das dplyr-package hat sich seitdem verändert. Daher lasse ich das folgende update. Ich hoffe das wird einigen helfen R Benutzer, zu lernen, wie
mutate_at()
.mutate_each()
ist jetzt veraltet. Sie verwenden möchtenmutate_at()
statt. Sie können angeben, welche Spalten Sie möchten, um Ihre Funktion in.vars
. Eine Möglichkeit ist die Verwendungvars()
. Ein anderer ist ein Zeichen-Vektor mit Spaltennamen, die Sie anwenden möchten, um Ihre benutzerdefinierte Funktion in.fun
. Die andere ist die Angabe von Spalten mit zahlen (z.B. 5:7 in diesem Fall). Beachten Sie, dass, wenn Sie eine Spalte fürgroup_by()
, müssen Sie ändern Sie die zahlen der Spalte Positionen. Schauen Sie sich diese Frage.Habe ich absichtlich gab
toAsset
zu der benutzerdefinierten Funktion in.fun
da dies wird mir helfen, einen neuen Spaltennamen. Eben habe ichrename()
. Aber ich denke, es ist viel einfacher zu reinigen Spaltennamen mitgsub()
im vorliegenden Ansatz. Wenn das obige Ergebnis wird gespeichert, wieout
Sie möchten, führen Sie den folgenden code, um zu entfernen_
in der Spalte Namen.Ursprüngliche Antwort
Denke ich, kann man sich Tipparbeit ersparen, in dieser Weise mit dplyr. Der Nachteil ist, Sie überschreiben, cash, Bonds und Kredite.
Wenn Sie es bevorzugen, Ihre erwarteten Ergebnisse, ich denke, einige Eingabe notwendig ist. Die Umbenennung Teil scheint etwas zu sein, was du tun musst.
ana <- bankdata %>% group_by(bankname) %>% summarise_each(funs(whatever = ./totass), cash:loans) %>% rename(cashtoAsset = cash, bondtoAsset = bond, loanstoAsset = loans); ana %>% merge(bankdata,., by = "bank name")
Apply
undcbind
apply
Funktion. Es bedeutet, dass die Funktion angewendet auf die Spalten-Vektor. "1" stattdessen würde die Funktion anwenden zu Reihen. ( überprüfen Sie?apply
)Hier ist ein
data.table
Lösung.Dies ist einer der großen Nachteile von
dplyr
: soweit ich weiß, gibt es keinen einfachen Weg, es zu benutzen, programmatisch eher als interaktiv ohne irgendeine Art von "hack", wie die bedauerlicheeval(parse(text=foo))
idiom.Die einfachste Vorgehensweise ist die gleiche wie in der Stata-Methode, aber die string-manipulation ist ein wenig Ausführlicher in R als in Stata (oder in irgendeiner anderen Skriptsprache, für diese Angelegenheit).
Machen die ganze Sache mehr Stata-wie, Sie können wickeln Sie das ganze in
within
etwa so:erfordert aber einige hacken mit der
get
undassign
Funktionen, die nicht als sicher für den Einsatz in Allgemeinen, obwohl in Ihrem Fall ist es wahrscheinlich keine große Sache. Ich würde nicht empfehlen, versuchen, ähnliche tricks, mitdplyr
zum Beispiel, weildplyr
Missbräuche R s nichtstandardisierte evaluation-Funktionen, und es ist wahrscheinlich mehr ärger als es Wert ist. Für eine schnellere und wahrscheinlich beste Lösung, schauen Sie sich diedata.table
- Paket, welches (glaube ich) ermöglicht die Verwendung des Stata-wie looping-syntax, jedoch mitdplyr
-wie Geschwindigkeit. Überprüfen Sie das Paket vignette auf CRAN.Außerdem sind Sie wirklich, wirklich sicher, dass Sie zuweisen möchten, die
NA
Einträge auf 0?Versuchen:
Ausgabe:
Sie machen vielleicht ein wenig härter als nötig. Nur versuchen, diese und sehen, ob Sie liefern, was Sie benötigen.
Ergibt dies:
Dieser sollte Ihnen den Einstieg in die richtige Richtung.