Ich habe einen Datenrahmen, und für jede Zeile in diesem Datenrahmen muss ich einige komplizierte Suchvorgänge durchführen und einige Daten an eine Datei anhängen.
Der dataFrame enthält wissenschaftliche Ergebnisse für ausgewählte Wells aus 96 Well-Platten, die in der biologischen Forschung verwendet werden. Ich möchte also Folgendes tun:
for (well in dataFrame) {
wellName <- well$name # string like "H1"
plateName <- well$plate # string like "plate67"
wellID <- getWellID(wellName, plateName)
cat(paste(wellID, well$value1, well$value2, sep=","), file=outputFile)
}
In meiner prozeduralen Welt würde ich so etwas tun:
for (row in dataFrame) {
#look up stuff using data from the row
#write stuff to the file
}
Was ist der "R-Weg", um dies zu tun?
Antworten:
Sie können dies mit der
apply()
Funktion versuchenquelle
x
) einen Vektor haben. Aus diesem Grund müssen im obigen Beispiel numerische Indizes verwendet werden. Mit dem by () -Ansatz erhalten Sie einen data.frame, der Ihren Code robuster macht.wellName <- x[1]
könnte auch seinwellName <- x["name"]
.Sie können die
by()
Funktion verwenden:Aber das direkte Durchlaufen der Zeilen ist selten das, was Sie wollen. Sie sollten stattdessen versuchen, zu vektorisieren. Kann ich fragen, was die eigentliche Arbeit in der Schleife macht?
quelle
1:0
seq_len(nrow(dataFrame))
anstelle von einzufügen1:nrow(dataFrame)
.dostuff
diese Antwort instr(row)
Sie sehen mehrere Zeilen in der Konsole, beginnend mit "'data.frame': 1 obs von x Variablen". Seien Sie jedoch vorsichtig, wenn Sie zu änderndostuff
,row
wird kein data.frame-Objekt für die äußere Funktion als Ganzes zurückgegeben. Stattdessen wird eine Liste von einzeiligen Datenrahmen zurückgegeben.Erstens ist Jonathans Argument zur Vektorisierung richtig. Wenn Ihre Funktion getWellID () vektorisiert ist, können Sie die Schleife überspringen und einfach cat oder write.csv verwenden:
Wenn getWellID () nicht vektorisiert ist, sollte Jonathans Empfehlung zur Verwendung
by
oder Knguyens Vorschlag vonapply
funktionieren.Andernfalls können Sie Folgendes
for
tun , wenn Sie es wirklich verwenden möchten :Sie können auch versuchen, das
foreach
Paket zu verwenden, obwohl Sie sich mit dieser Syntax vertraut machen müssen. Hier ist ein einfaches Beispiel:Eine letzte Option ist die Verwendung einer Funktion aus dem
plyr
Paket. In diesem Fall ist die Konvention der Apply-Funktion sehr ähnlich.quelle
mapply(getWellId, well$name, well$plate)
.foreach
- Ich werde die Hölle daraus machen.Ich denke, der beste Weg, dies mit Basic R zu tun, ist:
Der Vorteil gegenüber dem
for( i in 1:nrow(df))
Ansatz ist, dass Sie keine Probleme bekommen, wenndf
leer undnrow(df)=0
.quelle
Ich benutze diese einfache Utility-Funktion:
Oder eine schnellere, weniger klare Form:
Diese Funktion teilt nur einen data.frame in eine Liste von Zeilen auf. Dann können Sie ein normales "für" über diese Liste setzen:
Ihr Code aus der Frage funktioniert mit einer minimalen Änderung:
quelle
lapply
iteriert also über die Spalten des gesamten Datensatzesx
, gibt jeder Spalte den Namenc
und extrahiert dann deni
dritten Eintrag aus diesem Spaltenvektor. Ist das richtig?wellName <- as.character(well$name)
.Ich war neugierig auf die zeitliche Leistung der nicht vektorisierten Optionen. Zu diesem Zweck habe ich die von knguyen definierte Funktion f verwendet
und ein Datenrahmen wie der in seinem Beispiel:
Ich habe zwei vektorisierte Funktionen eingefügt (sicher schneller als die anderen), um den cat () -Ansatz mit einem write.table () zu vergleichen ...
Das resultierende Bild zeigt, dass apply die beste Leistung für eine nicht vektorisierte Version bietet, während write.table () cat () zu übertreffen scheint.
quelle
Sie können die
by_row
Funktion aus dem Paketpurrrlyr
dafür verwenden:Standardmäßig wird der zurückgegebene Wert von
myfn
in eine neue Listenspalte in der aufgerufenen df eingefügt.out
.Wenn dies die einzige Ausgabe ist, die Sie wünschen, können Sie schreiben
purrrlyr::by_row(df, myfn)$.out
quelle
Nun, da Sie nach R gefragt haben, das anderen Sprachen entspricht, habe ich versucht, dies zu tun. Scheint zu funktionieren, obwohl ich nicht wirklich untersucht habe, welche Technik in R effizienter ist.
Für die kategorialen Spalten wird jedoch ein Datenrahmen abgerufen, den Sie bei Bedarf mit as.character () typisieren können.
quelle