Setiap kali saya ingin melakukan sesuatu "memetakan" py dalam R, saya biasanya mencoba menggunakan fungsi dalam apply
keluarga.
Namun, saya tidak pernah benar-benar memahami perbedaan di antara mereka - bagaimana { sapply
,, lapply
dll} menerapkan fungsi ke input / input yang dikelompokkan, seperti apa outputnya, atau bahkan seperti apa inputnya - jadi saya sering hanya melalui mereka semua sampai saya mendapatkan apa yang saya inginkan.
Adakah yang bisa menjelaskan bagaimana cara menggunakannya kapan?
Pemahaman saya saat ini (mungkin salah / tidak lengkap) adalah ...
sapply(vec, f)
: input adalah vektor. Output adalah vektor / matriks, di mana elemeni
adalahf(vec[i])
, memberi Anda matriks jikaf
memiliki output multi-elemenlapply(vec, f)
: sama dengansapply
, tetapi output adalah daftar?apply(matrix, 1/2, f)
: input adalah sebuah matriks. output adalah vektor, di mana elemeni
adalah f (baris / kolom i dari matriks)tapply(vector, grouping, f)
: output adalah matriks / array, di mana elemen dalam matriks / array adalah nilaif
pada pengelompokang
vektor, dang
akan didorong ke nama baris / colby(dataframe, grouping, f)
: biarkang
menjadi pengelompokan. berlakuf
untuk setiap kolom grup / bingkai data. cukup cetak pengelompokan dan nilaif
di setiap kolom.aggregate(matrix, grouping, f)
: mirip denganby
, tetapi alih-alih mencetak hasil cetak, agregat menempelkan semuanya ke dalam kerangka data.
Pertanyaan sampingan: Saya masih belum belajar plyr atau membentuk kembali - akankah plyr
atau reshape
mengganti semuanya?
*apply()
danby
. plyr (setidaknya bagi saya) tampaknya jauh lebih konsisten karena saya selalu tahu persis format data apa yang diharapkannya dan apa yang akan dimuntahkannya. Itu menyelamatkan saya banyak kerumitan.doBy
dan pilihan & menerapkan kemampuandata.table
.sapply
hanyalapply
dengan penambahansimplify2array
pada output.apply
memang memaksa untuk vektor atom, tetapi output dapat berupa vektor atau daftar.by
membagi dataframe menjadi sub-dataframe, tetapi tidak digunakanf
pada kolom secara terpisah. Hanya jika ada metode untuk kelas 'data.frame' yang dapatf
diterapkan oleh kolomby
.aggregate
adalah metode generik sehingga berbeda untuk kelas yang berbeda dari argumen pertama.Jawaban:
R memiliki banyak * fungsi yang berlaku yang dapat dijelaskan dalam file bantuan (misalnya
?apply
). Ada cukup banyak dari mereka, bahwa penggunaan awal mungkin mengalami kesulitan dalam memutuskan mana yang sesuai untuk situasi mereka atau bahkan mengingat semuanya. Mereka mungkin memiliki pengertian umum bahwa "Saya harus menggunakan * menerapkan fungsi di sini", tetapi mungkin sulit untuk menjaga semuanya tetap lurus pada awalnya.Terlepas dari kenyataan (dicatat dalam jawaban lain) bahwa banyak fungsi * keluarga yang berlaku dicakup oleh
plyr
paket yang sangat populer , fungsi-fungsi dasar tetap berguna dan patut diketahui.Jawaban ini dimaksudkan untuk bertindak sebagai semacam rambu untuk pengguna baru untuk membantu mengarahkan mereka ke fungsi yang benar * berlaku untuk masalah khusus mereka. Catatan, ini tidak dimaksudkan hanya memuntahkan atau mengganti dokumentasi R! Harapannya adalah bahwa jawaban ini membantu Anda untuk memutuskan fungsi mana * yang sesuai dengan situasi Anda dan kemudian terserah Anda untuk merisetnya lebih lanjut. Dengan satu pengecualian, perbedaan kinerja tidak akan diatasi.
apply - Ketika Anda ingin menerapkan fungsi ke baris atau kolom matriks (dan analog berdimensi tinggi); umumnya tidak disarankan untuk frame data karena akan memaksa ke matriks terlebih dahulu.
Jika Anda ingin cara baris / kolom atau jumlah untuk matriks 2D, pastikan untuk menyelidiki sangat optimal, kilat-cepat
colMeans
,rowMeans
,colSums
,rowSums
.lapply - Ketika Anda ingin menerapkan fungsi pada setiap elemen daftar pada gilirannya dan mendapatkan daftar kembali.
Ini adalah pekerja keras dari banyak fungsi * lainnya yang berlaku. Kupas kembali kode mereka dan Anda akan sering menemukan di
lapply
bawahnya.sapply - Ketika Anda ingin menerapkan fungsi ke setiap elemen daftar pada gilirannya, tetapi Anda ingin vektor kembali, bukan daftar.
Jika Anda mengetik
unlist(lapply(...))
, hentikan dan pertimbangkansapply
.Dalam penggunaan yang lebih maju
sapply
akan mencoba untuk memaksa hasilnya ke array multi-dimensi, jika sesuai. Misalnya, jika fungsi kami mengembalikan vektor dengan panjang yang sama,sapply
akan menggunakannya sebagai kolom dari sebuah matriks:Jika fungsi kita mengembalikan matriks 2 dimensi,
sapply
pada dasarnya akan melakukan hal yang sama, memperlakukan setiap matriks yang dikembalikan sebagai vektor panjang tunggal:Kecuali kita tentukan
simplify = "array"
, dalam hal ini akan menggunakan matriks individu untuk membangun array multi-dimensi:Setiap perilaku ini tentu saja bergantung pada fungsi kita yang mengembalikan vektor atau matriks dengan panjang atau dimensi yang sama.
vapply - Ketika Anda ingin menggunakan
sapply
tetapi mungkin perlu memeras lebih cepat dari kode Anda.Sebab
vapply
, pada dasarnya Anda memberi R contoh hal apa yang akan dikembalikan fungsi Anda, yang bisa menghemat waktu untuk memaksa nilai yang dikembalikan agar sesuai dengan satu vektor atom.mapply - Untuk ketika Anda memiliki beberapa struktur data (misalnya vektor, daftar) dan Anda ingin menerapkan fungsi ke elemen 1 masing-masing, dan kemudian elemen 2 masing-masing, dll., memaksa hasil ke vektor / array seperti di
sapply
.Ini multivarian dalam arti bahwa fungsi Anda harus menerima banyak argumen.
Peta - Pembungkus
mapply
denganSIMPLIFY = FALSE
, sehingga dijamin akan mengembalikan daftar.rapply - Untuk saat Anda ingin menerapkan fungsi ke setiap elemen struktur daftar bersarang , secara rekursif.
Untuk memberi tahu Anda betapa tidak lazimnya
rapply
, saya lupa ketika pertama kali memposting jawaban ini! Jelas, saya yakin banyak orang yang menggunakannya, tapi YMMV.rapply
paling baik diilustrasikan dengan fungsi yang ditentukan pengguna untuk diterapkan:tapply - Untuk saat Anda ingin menerapkan fungsi ke subset vektor dan subset ditentukan oleh beberapa vektor lain, biasanya faktor.
Domba hitam dari keluarga * berlaku, semacam. Penggunaan file bantuan dari frasa "array kasar" bisa sedikit membingungkan , tetapi sebenarnya cukup sederhana.
Vektor:
Faktor yang mendefinisikan (dengan panjang yang sama!):
Tambahkan nilai-nilai di
x
dalam setiap subkelompok yang ditentukan olehy
:Contoh yang lebih kompleks dapat ditangani di mana subkelompok ditentukan oleh kombinasi unik dari daftar beberapa faktor.
tapply
adalah semangat yang sama split-berlaku-menggabungkan fungsi yang umum dalam R (aggregate
,by
,ave
,ddply
, dll) Oleh karena itu statusnya kambing hitam.sumber
by
adalah murni split-lapply danaggregate
adalahtapply
pada intinya. Saya pikir domba hitam membuat kain yang bagus.aggregate
danby
juga? (Saya akhirnya memahaminya setelah uraian Anda !, tetapi itu cukup umum, jadi mungkin berguna untuk memisahkan dan memiliki beberapa contoh spesifik untuk kedua fungsi tersebut.)aggregate
,,by
dll didasarkan pada * menerapkan fungsi, cara Anda mendekati menggunakannya cukup berbeda dari perspektif pengguna sehingga mereka harus dirangkum dalam jawaban yang terpisah. Saya mungkin berusaha jika saya punya waktu, atau mungkin orang lain akan mengalahkan saya untuk itu dan mendapatkan upvote saya.?Map
sebagai kerabatmapply
data.frame
s adalah bagian yang sangat penting dari R dan sebagailist
objek yang sering dimanipulasi dengan menggunakanlapply
khususnya. Mereka juga bertindak sebagai wadah untuk mengelompokkan vektor / faktor dari banyak jenis bersama-sama dalam dataset persegi panjang tradisional. Sementaradata.table
danplyr
mungkin menambahkan jenis sintaks tertentu yang beberapa mungkin merasa lebih nyaman, mereka memperluas dan bertindakdata.frame
masing-masing.Di samping catatan, berikut adalah bagaimana berbagai
plyr
fungsi sesuai dengan*apply
fungsi dasar (dari pengantar ke dokumen plyr dari halaman web plyr http://had.co.nz/plyr/ )Salah satu tujuannya
plyr
adalah untuk memberikan konvensi penamaan yang konsisten untuk setiap fungsi, menyandikan tipe data input dan output dalam nama fungsi. Ini juga memberikan konsistensi dalam output, di mana output daridlply()
mudah dilaluildply()
untuk menghasilkan output yang bermanfaat, dll.Secara konseptual, belajar
plyr
tidak lebih sulit daripada memahami*apply
fungsi-fungsi dasar .plyr
danreshape
fungsi telah menggantikan hampir semua fungsi ini dalam penggunaan saya setiap hari. Tapi, juga dari dokumen Intro ke Plyr:sumber
*apply()
keluarga fungsi. Bagi saya,ddply()
sangat intuitif karena saya terbiasa dengan fungsi agregasi SQL.ddply()
menjadi palu saya untuk memecahkan banyak masalah, beberapa di antaranya bisa diselesaikan dengan lebih baik dengan perintah lain.plyr
fungsi mirip dengan*apply
fungsi, jadi jika Anda bisa melakukan satu, Anda bisa melakukan yang lain, tetapiplyr
fungsi lebih mudah diingat. Tapi saya sepenuhnya setuju denganddply()
palu!join()
fungsi yang melakukan tugas-tugas yang mirip dengan penggabungan. Mungkin lebih tepat untuk menyebutkannya dalam konteks plyr.eapply
vapply
dan kelemahannyasapply
. Keuntungan utamavapply
adalah bahwa ia menegakkan tipe dan panjang keluaran, sehingga Anda akan berakhir dengan output yang diharapkan secara tepat atau kesalahan informatif. Di sisi lain,sapply
akan mencoba menyederhanakan output mengikuti aturan yang tidak selalu jelas, dan kembali ke daftar sebaliknya. Sebagai contoh, cobalah untuk memprediksi jenis output ini akan menghasilkan:sapply(list(1:5, 6:10, matrix(1:4, 2)), function(x) head(x, 1))
. Bagaimana dengansapply(list(matrix(1:4, 2), matrix(1:4, 2)), ...)
?Dari slide 21 dari http://www.slideshare.net/hadley/plyr-one-data-analytic-strategy :
(Semoga jelas bahwa
apply
berkorespondensi dengan @ Hadley'saaply
danaggregate
berkorespondensi dengan @ Hadley's,ddply
dll. Slide 20 dari slideshare yang sama akan menjelaskan jika Anda tidak mendapatkannya dari gambar ini.)(di sebelah kiri adalah input, di atas adalah output)
sumber
Pertama-tama mulailah dengan jawaban Joran yang luar biasa - keraguan apa pun bisa lebih baik dari itu.
Kemudian mnemonik berikut dapat membantu untuk mengingat perbedaan antara masing-masing. Sementara beberapa jelas, yang lain mungkin kurang begitu --- untuk ini Anda akan menemukan pembenaran dalam diskusi Joran.
Ilmu tentang cara menghafal
lapply
adalah daftar yang berlaku yang bertindak pada daftar atau vektor dan mengembalikan daftar.sapply
adalah sederhanalapply
(default fungsi untuk kembali vektor atau matriks bila memungkinkan)vapply
adalah terverifikasi yang berlaku (memungkinkan tipe objek kembali yang ditentukan sebelumnya)rapply
adalah aplikasi rekursif untuk daftar bersarang, yaitu daftar dalam daftartapply
adalah tag yang berlaku di mana tag mengidentifikasi subsetapply
adalah generik : berlaku fungsi untuk baris atau kolom matriks (atau, lebih umum, untuk dimensi array)Membangun Latar Belakang yang Tepat
Jika menggunakan
apply
keluarga itu masih terasa asing bagi Anda, mungkin Anda kehilangan sudut pandang kunci.Dua artikel ini dapat membantu. Mereka memberikan latar belakang yang diperlukan untuk memotivasi teknik pemrograman fungsional yang disediakan oleh
apply
keluarga fungsi.Pengguna Lisp akan mengenali paradigma dengan segera. Jika Anda tidak terbiasa dengan Lisp, begitu Anda mengenal FP, Anda akan memiliki sudut pandang yang kuat untuk digunakan dalam R - dan
apply
akan jauh lebih masuk akal.sumber
Karena saya menyadari bahwa (sangat bagus) jawaban dari kurangnya posting
by
danaggregate
penjelasan. Ini kontribusi saya.OLEH
The
by
fungsi, seperti yang dinyatakan dalam dokumentasi dapat meskipun, sebagai "pembungkus" untuktapply
. Kekuatanby
muncul ketika kita ingin menghitung tugas yangtapply
tidak bisa ditangani. Salah satu contohnya adalah kode ini:Jika kita mencetak dua objek ini,
ct
dancb
, kita "pada dasarnya" memiliki hasil yang sama dan satu-satunya perbedaan adalah bagaimana mereka ditampilkan danclass
atribut yang berbeda , masingby
- masing untukcb
danarray
untukct
.Seperti yang telah saya katakan, kekuatan
by
muncul ketika kita tidak dapat menggunakantapply
; kode berikut adalah salah satu contoh:R mengatakan bahwa argumen harus memiliki panjang yang sama, katakan "kita ingin menghitung
summary
semua variabel diiris
sepanjang faktorSpecies
": tetapi R tidak bisa melakukan itu karena tidak tahu cara menangani.Dengan
by
fungsi R memberangkatkan metode khusus untukdata frame
kelas dan kemudian membiarkansummary
fungsi tersebut bekerja bahkan jika panjang argumen pertama (dan tipenya juga) berbeda.ini memang berhasil dan hasilnya sangat mengejutkan. Ini adalah objek kelas
by
yang sepanjangSpecies
(katakanlah, untuk masing-masing dari mereka) menghitungsummary
setiap variabel.Perhatikan bahwa jika argumen pertama adalah a
data frame
, fungsi yang dikirim harus memiliki metode untuk kelas objek tersebut. Sebagai contoh adalah kita menggunakan kode ini denganmean
fungsi kita akan memiliki kode ini yang tidak masuk akal sama sekali:AGREGAT
aggregate
dapat dilihat sebagai cara penggunaan yang berbedatapply
jika kita menggunakannya sedemikian rupa.Dua perbedaan langsung adalah bahwa argumen kedua
aggregate
harus daftar sementaratapply
bisa (tidak wajib) menjadi daftar dan bahwa outputaggregate
adalah bingkai data sedangkan yang salahtapply
adalaharray
.Kekuatannya
aggregate
adalah ia dapat menangani subset data dengan mudah dengansubset
argumen dan memiliki metode untukts
objek danformula
juga.Elemen-elemen ini
aggregate
memudahkan untuk bekerja dengan itutapply
dalam beberapa situasi. Berikut adalah beberapa contoh (tersedia dalam dokumentasi):Kita dapat mencapai hal yang sama dengan
tapply
tetapi sintaks sedikit lebih sulit dan output (dalam beberapa keadaan) kurang dapat dibaca:Ada saat-saat lain ketika kita tidak dapat menggunakan
by
atautapply
dan kita harus menggunakannyaaggregate
.Kami tidak dapat memperoleh hasil sebelumnya dengan
tapply
satu panggilan, tetapi kami harus menghitung rata-rataMonth
untuk setiap elemen dan kemudian menggabungkannya (juga perhatikan bahwa kami harus memanggilna.rm = TRUE
, karenaformula
metodeaggregate
fungsi secara defaultna.action = na.omit
):sementara dengan
by
kita tidak bisa mencapai itu pada kenyataannya panggilan fungsi berikut mengembalikan kesalahan (tetapi kemungkinan besar itu terkait dengan fungsi yang disediakan,mean
):Lain kali hasilnya sama dan perbedaannya hanya di kelas (dan kemudian bagaimana itu ditampilkan / dicetak dan tidak hanya - contoh, cara subset itu) objek:
Kode sebelumnya mencapai tujuan dan hasil yang sama, pada beberapa titik alat apa yang digunakan hanyalah masalah selera dan kebutuhan pribadi; dua objek sebelumnya memiliki kebutuhan yang sangat berbeda dalam hal pengaturan ulang.
sumber
data.frame(tapply(unlist(iris[,-5]),list(rep(iris[,5],ncol(iris[-5])),col(iris[-5])),summary))
Ini adalah penggunaan tapply. With the right splitting there is nothing you cant do with
tapply. The only thing is it returns a matrix. Please be careful by saying we cant use
tapply`Ada banyak jawaban hebat yang membahas perbedaan dalam kasus penggunaan untuk setiap fungsi. Tidak ada jawaban yang membahas perbedaan kinerja. Itu wajar karena berbagai fungsi mengharapkan berbagai input dan menghasilkan berbagai output, namun kebanyakan dari mereka memiliki tujuan umum bersama untuk mengevaluasi secara seri / kelompok. Jawaban saya akan fokus pada kinerja. Karena di atas penciptaan input dari vektor termasuk dalam pengaturan waktu, juga
apply
fungsi tidak diukur.Saya telah menguji dua fungsi yang berbeda
sum
danlength
sekaligus. Volume yang diuji adalah 50M pada input dan 50K pada output. Saya juga menyertakan dua paket populer saat ini yang tidak banyak digunakan pada saat pertanyaan diajukan,data.table
dandplyr
. Keduanya pasti layak dilihat jika Anda mengincar kinerja yang baik.sumber
Terlepas dari semua jawaban hebat di sini, ada 2 fungsi dasar lagi yang layak disebutkan, yang bermanfaat
outer
fungsi dan jelaseapply
fungsiluar
outer
adalah fungsi yang sangat berguna disembunyikan sebagai yang lebih biasa. Jika Anda membaca bantuan untukouter
deskripsinya mengatakan:yang membuatnya tampak seperti ini hanya berguna untuk hal-hal jenis aljabar linier. Namun, dapat digunakan seperti
mapply
menerapkan fungsi ke dua vektor input. Perbedaannya adalah bahwamapply
akan menerapkan fungsi ke dua elemen pertama dan kemudian kedua kedua dll, sedangkanouter
akan menerapkan fungsi untuk setiap kombinasi satu elemen dari vektor pertama dan satu dari yang kedua. Sebagai contoh:Saya secara pribadi menggunakan ini ketika saya memiliki vektor nilai dan vektor kondisi dan ingin melihat nilai mana yang memenuhi kondisi mana.
dengan mudah
eapply
sepertilapply
kecuali bahwa alih-alih menerapkan fungsi ke setiap elemen dalam daftar, itu berlaku fungsi untuk setiap elemen dalam lingkungan. Misalnya jika Anda ingin menemukan daftar fungsi yang ditentukan pengguna di lingkungan global:Terus terang saya tidak menggunakan ini terlalu banyak tetapi jika Anda membangun banyak paket atau membuat banyak lingkungan mungkin berguna.
sumber
Mungkin perlu disebutkan
ave
.ave
adalahtapply
sepupu ramah. Ini mengembalikan hasil dalam bentuk yang dapat Anda pasang langsung kembali ke bingkai data Anda.Tidak ada dalam paket dasar yang berfungsi seperti
ave
untuk seluruh frame data (sepertiby
halnyatapply
untuk frame data). Tapi Anda bisa memperdayainya:sumber
Saya baru-baru menemukan yang agak berguna
sweep
dan menambahkannya di sini demi kelengkapan:menyapu
Ide dasarnya adalah menyapu melalui array baris atau kolom dan mengembalikan array yang dimodifikasi. Contoh akan memperjelas ini (sumber: datacamp ):
Katakanlah Anda memiliki matriks dan ingin membakukannya dengan bijaksana kolom:
NB: untuk contoh sederhana ini hasil yang sama tentu saja dapat dicapai dengan lebih mudah
apply(dataPoints, 2, scale)
sumber
sweep
adalah fungsi tingkat tinggi seperti yang lain yang disebutkan di sini, misalnyaapply
,sapply
,lapply
Jadi pertanyaan yang sama bisa ditanya tentang jawaban yang diterima dengan lebih dari 1.000 upvotes dan contoh yang diberikan di dalamnya. Lihat saja contoh yang diberikan diapply
sana.sweep(matrix(1:6,nrow=2),2,7:9,list)
. Ini biasanya lebih efisien daripadaapply
karena di manaapply
loop,sweep
dapat menggunakan fungsi vektor.Dalam paket runtuh yang baru-baru ini dirilis di CRAN, saya telah mencoba untuk mengkompres sebagian besar fungsi yang berlaku umum menjadi hanya 2 fungsi:
dapply
(Data-Apply) menerapkan fungsi ke baris atau kolom (standar) dari matriks dan data.frame dan (default) mengembalikan objek dengan tipe yang sama dan dengan atribut yang sama (kecuali jika hasil dari setiap perhitungan adalah atom dandrop = TRUE
). Kinerja ini sebanding denganlapply
untuk kolom data.frame, dan sekitar 2x lebih cepat daripadaapply
untuk baris atau kolom matriks. Paralelisme tersedia melaluimclapply
(hanya untuk MAC).Sintaksis:
Contoh:
BY
adalah generik S3 untuk komputasi split-apply-menggabungkan dengan metode vektor, matriks dan data.frame. Ini secara signifikan lebih cepat daripadatapply
,by
danaggregate
(juga lebih cepat daripadaplyr
, pada data besardplyr
lebih cepat).Sintaksis:
Contoh:
Daftar variabel pengelompokan juga dapat diberikan
g
.Berbicara tentang kinerja: Tujuan utama keruntuhan adalah untuk mendorong pemrograman berkinerja tinggi di R dan untuk bergerak melampaui split-apply-menggabungkan semuanya. Untuk tujuan ini paket memiliki set lengkap C ++ berdasarkan fungsi cepat generik:
fmean
,fmedian
,fmode
,fsum
,fprod
,fsd
,fvar
,fmin
,fmax
,ffirst
,flast
,fNobs
,fNdistinct
,fscale
,fbetween
,fwithin
,fHDbetween
,fHDwithin
,flag
,fdiff
danfgrowth
. Mereka melakukan perhitungan yang dikelompokkan dalam satu melewati data (yaitu tidak ada pemisahan dan penggabungan kembali).Sintaksis:
Contoh:
Dalam sketsa paket saya memberikan tolok ukur. Pemrograman dengan fungsi cepat secara signifikan lebih cepat daripada pemrograman dengan dplyr atau data . Tabel , terutama pada data yang lebih kecil, tetapi juga pada data besar.
sumber