Saya memiliki dataframe, dan untuk setiap baris dalam dataframe saya harus melakukan beberapa pencarian rumit dan menambahkan beberapa data ke file.
DataFrame berisi hasil-hasil ilmiah untuk sumur-sumur terpilih dari 96 pelat sumur yang digunakan dalam penelitian biologi, jadi saya ingin melakukan sesuatu seperti:
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)
}
Di dunia prosedural saya, saya akan melakukan sesuatu seperti:
for (row in dataFrame) {
#look up stuff using data from the row
#write stuff to the file
}
Apa "cara R" untuk melakukan ini?
Jawaban:
Anda dapat mencoba ini, menggunakan
apply()
fungsisumber
x
) adalah vektor. Inilah sebabnya mengapa contoh di atas harus menggunakan indeks numerik; pendekatan by () memberi Anda data.frame, yang membuat kode Anda lebih kuat.wellName <- x[1]
bisa juga bisawellName <- x["name"]
.Anda dapat menggunakan
by()
fungsi ini:Tapi iterasi pada baris langsung seperti ini jarang yang Anda inginkan; Anda harus mencoba membuat vektor sebagai gantinya. Bisakah saya bertanya apa yang sebenarnya dilakukan dalam loop?
sumber
1:0
tidak kosongseq_len(nrow(dataFrame))
di tempat1:nrow(dataFrame)
.dostuff
jawaban ini untukstr(row)
Anda akan melihat beberapa baris dicetak di konsol dimulai dengan "'data.frame': 1 obs of x variable." Tapi hati-hati, mengubahdostuff
untukrow
tidak mengembalikan objek data.frame untuk fungsi luar secara keseluruhan. Alih-alih itu mengembalikan daftar satu frame data-baris.Pertama, poin Jonathan tentang vektorisasi adalah benar. Jika fungsi getWellID () Anda adalah vektor, maka Anda dapat melewati loop dan cukup menggunakan cat atau write.csv:
Jika getWellID () tidak di-vectorized, maka rekomendasi Jonathan untuk menggunakan
by
atau saran knguyen tentangapply
harus bekerja.Jika tidak, jika Anda benar-benar ingin menggunakannya
for
, Anda dapat melakukan sesuatu seperti ini:Anda juga dapat mencoba menggunakan
foreach
paket, meskipun mengharuskan Anda untuk terbiasa dengan sintaks itu. Berikut ini contoh sederhana:Opsi terakhir adalah menggunakan fungsi di luar
plyr
paket, dalam hal ini konvensi akan sangat mirip dengan fungsi yang berlaku.sumber
mapply(getWellId, well$name, well$plate)
.foreach
- Saya akan menggunakan yang itu.Saya pikir cara terbaik untuk melakukan ini dengan R dasar adalah:
Keuntungan daripada
for( i in 1:nrow(df))
pendekatan-adalah bahwa Anda tidak mendapat masalah jikadf
kosong dannrow(df)=0
.sumber
Saya menggunakan fungsi utilitas sederhana ini:
Atau bentuk yang lebih cepat, kurang jelas:
Fungsi ini hanya membagi data.frame menjadi daftar baris. Kemudian Anda dapat membuat "untuk" yang normal pada daftar ini:
Kode Anda dari pertanyaan akan berfungsi dengan modifikasi minimal:
sumber
lapply
iterates atas kolom seluruh datasetx
, memberikan nama masing-masing kolomc
, dan kemudian mengekstraksii
entri th dari vektor kolom itu. Apakah ini benar?wellName <- as.character(well$name)
.Saya ingin tahu tentang kinerja waktu dari opsi non-vektor. Untuk tujuan ini, saya telah menggunakan fungsi f yang didefinisikan oleh knguyen
dan bingkai data seperti yang ada dalam contohnya:
Saya menyertakan dua fungsi vektor (pasti lebih cepat dari yang lain) untuk membandingkan pendekatan cat () dengan metode write.table () ...
Gambar yang dihasilkan menunjukkan bahwa penerapan memberikan kinerja terbaik untuk versi non-vektor, sedangkan write.table () tampaknya mengungguli cat ().
sumber
Anda dapat menggunakan
by_row
fungsi dari paketpurrrlyr
untuk ini:Secara default, nilai yang dikembalikan dari
myfn
dimasukkan ke dalam kolom daftar baru di df yang dipanggil.out
.Jika ini adalah satu-satunya hasil yang Anda inginkan, Anda dapat menulis
purrrlyr::by_row(df, myfn)$.out
sumber
Yah, karena Anda meminta R yang setara dengan bahasa lain, saya mencoba melakukan ini. Tampaknya bekerja meskipun saya belum benar-benar melihat teknik mana yang lebih efisien dalam R.
Untuk kolom kategorikal, ia akan mengambil Anda sebuah Frame Data yang bisa Anda ketik menggunakan as.character () jika diperlukan.
sumber