Auswählen von Elementen aus einer Liste: Wie eine Schleife in R zu vermeiden
Frage
Ich kann dies mit Schleifen lösen, aber ich versuche, denkt in Vektoren so mein Code mehr R-esque sein wird.
ich eine Liste von Namen haben. Das Format ist firstname_lastname. Ich möchte eine separate Liste von dieser Liste, um aus nur mit den Vornamen. Ich kann meine Gedanken nicht zu umgehen scheinen, wie dies zu tun. Hier einige Beispieldaten:
t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
tsplit <- strsplit(t,"_")
, die wie folgt aussehen:
> tsplit
[[1]]
[1] "bob" "smith"
[[2]]
[1] "mary" "jane"
[[3]]
[1] "jose" "chung"
[[4]]
[1] "michael" "marx"
[[5]]
[1] "charlie" "ivan"
Ich konnte raus, was ich will mit Schleifen wie folgt aus:
for (i in 1:length(tsplit)){
if (i==1) {t_out <- tsplit[[i]][1]} else{t_out <- append(t_out, tsplit[[i]][1])}
}
, die geben würde mir diese:
t_out
[1] "bob" "mary" "jose" "michael" "charlie"
Wie kann ich dies tun, ohne Schleifen?
Lösung
Sie können mit apply
(oder sapply
)
t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
f <- function(s) strsplit(s, "_")[[1]][1]
sapply(t, f)
bob_smith mary_jane jose_chung michael_marx charlie_ivan
"bob" "mary" "jose" "michael" "charlie"
Siehe auch: Eine kurze Einführung in R
„Übernehmen“Andere Tipps
Und noch ein Ansatz:
t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
pieces <- strsplit(t,"_")
sapply(pieces, "[", 1)
In Worten, die letzte Zeile extrahiert das erste Element jeder Komponente der Liste und dann vereinfacht es in einen Vektor.
Wie funktionierts? Nun, Sie müssen eine alternative Art und Weise realisieren x[1]
des Schreibens ist "["(x, 1)
, das heißt, es ist eine Funktion namens [
, die nicht subsetting. Der sapply
Aufruf gilt Anrufe diese Funktion einmal für jedes Element der ursprünglichen Liste, in zwei Argumenten zu übergeben, das Listenelement und 1.
Der Vorteil dieses Ansatzes gegenüber den anderen ist, dass Sie, ohne dass mehrere Elemente aus der Liste zu extrahieren, der die Spalten neu zu berechnen. Zum Beispiel würde der letzte Name sapply(pieces, "[", 2)
werden. Sobald Sie in dieses Idiom zu gewöhnen, ist es ziemlich einfach zu lesen.
Wie wäre:
tlist <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
fnames <- gsub("(_.*)$", "", tlist)
# _.* matches the underscore followed by a string of characters
# the $ anchors the search at the end of the input string
# so, underscore followed by a string of characters followed by the end of the input string
für den RegEx Ansatz?
was ist:
t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
sub("_.*", "", t)
Ich bezweifle, dass dies die eleganteste Lösung, aber es schlägt Looping:
t.df <- data.frame(tsplit)
t.df[1, ]
Listen Datenrahmen Konvertieren ist über die einzige Art, wie ich sie bekommen kann zu tun, was ich will. Ich freue mich auf Antworten von Menschen zu lesen, die tatsächlich verstehen, wie Listen zu handhaben.
Sie fast hatte. Es wirklich ist nur eine Frage der
- Mithilfe der
*apply
Funktionen in einer Schleife über die bestehende Liste, beginne ich oft mitlapply
und manchmal wechselnsapply
- fügen Sie eine anonyme Funktion, die zu einer Zeit auf einem der Listenelemente arbeitet
- Sie bereits wusste, es war
strsplit(string, splitterm)
und dass Sie die ungerade[[1]][1]
brauchen die erste Laufzeit der Antwort pflücken
- es nur alle zusammen mit einem bevorzugten variablen namne beginnen (wie wir klar von
t
oderc
und Freunden zu bleiben)
das gibt
> tlist <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
> fnames <- sapply(tlist, function(x) strsplit(x, "_")[[1]][1])
> fnames
bob_smith mary_jane jose_chung michael_marx charlie_ivan
"bob" "mary" "jose" "michael" "charlie"
>
Sie könnten unlist()
verwenden:
> tsplit <- unlist(strsplit(t,"_"))
> tsplit
[1] "bob" "smith" "mary" "jane" "jose" "chung" "michael"
[8] "marx" "charlie" "ivan"
> t_out <- tsplit[seq(1, length(tsplit), by = 2)]
> t_out
[1] "bob" "mary" "jose" "michael" "charlie"
Es könnte eine bessere Art und Weise sein, nur die ungeraden indizierte Einträge zu ziehen, aber in jedem Fall, dass Sie nicht eine Schleife haben.
Und ein anderer Ansatz, der auf brentonk des fehlenden oder Beispiel ...
tlist <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
tsplit <- unlist(strsplit(tlist,"_"))
fnames <- tsplit[seq(1:length(tsplit))%%2 == 1]
Ich würde verwenden Sie die folgende fehlenden oder () - Methode auf Basis:
> t <- c("bob_smith","mary_jane","jose_chung","michael_marx","charlie_ivan")
> tsplit <- strsplit(t,"_")
>
> x <- matrix(unlist(tsplit), 2)
> x[1,]
[1] "bob" "mary" "jose" "michael" "charlie"
Der große Vorteil dieser Methode ist, dass es das Äquivalent Problem für Nachnamen, die gleichzeitig löst:
> x[2,]
[1] "smith" "jane" "chung" "marx" "ivan"
Der Nachteil ist, dass Sie sicher sein müssen, werden feststellen, dass alle Namen auf die firstname_lastname
Struktur entsprechen; wenn überhaupt nicht, dann wird diese Methode brechen.
aus dem ursprünglichen Objekt tsplit
Liste am Anfang gegeben, wird dieser Befehl tun:
unlist(lapply(tsplit,function(x) x[1]))
es extrahiert das erste Element aller Listenelemente, wandelt dann eine Liste mit einem Vektor. Entadressierung zunächst auf eine Matrix, dann die Faust Säule Extraktion ist auch in Ordnung, aber dann sind Sie auf der Tatsache abhängig, dass alle Listenelemente die gleiche Länge haben. Hier ist die Ausgabe:
> tsplit
[[1]]
[1] "bob" "smith"
[[2]]
[1] "mary" "jane"
[[3]]
[1] "jose" "chung"
[[4]]
[1] "michael" "marx"
[[5]]
[1] "charlie" "ivan"
> lapply(tsplit,function(x) x[1])
[[1]]
[1] "bob"
[[2]]
[1] "mary"
[[3]]
[1] "jose"
[[4]]
[1] "michael"
[[5]]
[1] "charlie"
> unlist(lapply(tsplit,function(x) x[1]))
[1] "bob" "mary" "jose" "michael" "charlie"