Saya ingin mengurutkan data.frame dengan beberapa kolom. Sebagai contoh, dengan data.frame di bawah ini saya ingin mengurutkan berdasarkan kolom z
(turun) kemudian dengan kolom b
(naik):
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"),
levels = c("Low", "Med", "Hi"), ordered = TRUE),
x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
z = c(1, 1, 1, 2))
dd
b x y z
1 Hi A 8 1
2 Med D 3 1
3 Hi A 9 1
4 Low C 9 2
with
. CobalahM <- matrix(c(1,2,2,2,3,6,4,5), 4, 2, byrow=FALSE, dimnames=list(NULL, c("a","b")))
untuk membuat matriksM
, kemudian gunakanM[order(M[,"a"],-M[,"b"]),]
untuk memesannya di dua kolom.dd[ order(-dd[,4], dd[,1]), ]
tetapi tidak dapat digunakanwith
untuk pengaturan ulang berbasis nama.xtfrm
, misalnyadd[ order(-xtfrm(dd[,4]), dd[,1]), ]
.Pilihan anda
order
daribase
arrange
daridplyr
setorder
dansetorderv
daridata.table
arrange
dariplyr
sort
daritaRifx
orderBy
daridoBy
sortData
dariDeducer
Sebagian besar waktu Anda harus menggunakan
dplyr
ataudata.table
solusi, kecuali tidak memiliki ketergantungan adalah penting, dalam hal ini digunakanbase::order
.Saya baru-baru ini menambahkan sort.data.frame ke paket CRAN, menjadikannya kompatibel dengan kelas seperti yang dibahas di sini: Cara terbaik untuk membuat konsistensi generik / metode untuk sort.data.frame?
Oleh karena itu, mengingat data.frame dd, Anda dapat mengurutkan sebagai berikut:
Jika Anda adalah salah satu penulis asli dari fungsi ini, silakan hubungi saya. Diskusi mengenai domain publik ada di sini: http://chat.stackoverflow.com/transcript/message/1094290#1094290
Anda juga dapat menggunakan
arrange()
fungsi dariplyr
seperti yang Hadley tunjukkan di utas di atas:Benchmark: Perhatikan bahwa saya memuat setiap paket dalam sesi R baru karena ada banyak konflik. Khususnya memuat paket doBy yang menyebabkan
sort
pengembalian "Objek berikut ini disembunyikan dari 'x (posisi 17)': b, x, y, z", dan memuat paket Deducer menimpasort.data.frame
dari Kevin Wright atau paket taRifx.Waktu rata-rata:
dd[with(dd, order(-z, b)), ]
778dd[order(-dd$z, dd$b),]
788Waktu rata-rata: 1,567
Waktu rata-rata: 862
Waktu rata-rata: 1,694
Perhatikan bahwa doBy membutuhkan sedikit waktu untuk memuat paket.
Tidak dapat membuat Deducer memuat. Membutuhkan konsol JGR.
Tampaknya tidak kompatibel dengan microbenchmark karena melampirkan / melepaskan.
(garis memanjang dari kuartil bawah ke kuartil atas, titik adalah median)
Mengingat hasil ini dan menimbang kesederhanaan vs kecepatan, saya harus memberi anggukan
arrange
padaplyr
paket . Ia memiliki sintaksis yang sederhana namun hampir sama cepatnya dengan perintah R dasar dengan intrik yang berbelit-belit. Pekerjaan Hadley Wickham yang biasanya brilian. Satu-satunya keluhan saya dengan itu adalah bahwa itu melanggar nomenklatur R standar di mana objek penyortiran dipanggilsort(object)
, tapi saya mengerti mengapa Hadley melakukannya seperti itu karena masalah yang dibahas dalam pertanyaan yang terkait di atas.sumber
taRifx::autoplot.microbenchmark
.b
diurutkan dalam sampel. Defaultnya adalah mengurutkan dengan menaik, jadi Anda tidak perlu membungkusnyadesc
. Naik di kedua:arrange(dd,z,b)
. Turun di kedua:arrange(dd,desc(z),desc(b))
.?arrange
: "# CATATAN: fungsi plyr JANGAN pertahankan row.names". Ini membuatarrange()
fungsi yang sangat baik menjadi suboptimal jika seseorang ingin mempertahankannyarow.names
.Jawaban Dirk sangat bagus. Itu juga menyoroti perbedaan utama dalam sintaks yang digunakan untuk pengindeksan
data.frame
dandata.table
s:Perbedaan antara kedua panggilan itu kecil, tetapi dapat memiliki konsekuensi penting. Terutama jika Anda menulis kode produksi dan / atau berkaitan dengan kebenaran dalam penelitian Anda, yang terbaik adalah menghindari pengulangan nama variabel yang tidak perlu.
data.table
membantu kamu melakukan ini.Berikut adalah contoh bagaimana pengulangan nama variabel dapat membuat Anda mendapat masalah:
Mari kita ubah konteks dari jawaban Dirk, dan katakan ini adalah bagian dari proyek yang lebih besar di mana ada banyak nama objek dan mereka panjang dan bermakna; bukannya
dd
disebutquarterlyreport
. Menjadi :Baiklah. Tidak ada yang salah dengan itu. Selanjutnya bos Anda meminta Anda untuk memasukkan laporan kuartal terakhir dalam laporan. Anda membaca kode Anda, menambahkan objek
lastquarterlyreport
di berbagai tempat dan entah bagaimana (bagaimana?) Anda berakhir dengan ini:Bukan itu yang Anda maksudkan tetapi Anda tidak menemukannya karena Anda melakukannya dengan cepat dan terletak pada halaman kode yang sama. Kode tidak jatuh (tidak ada peringatan dan tidak ada kesalahan) karena R menganggap itu yang Anda maksud. Anda akan berharap siapa pun yang membaca laporan Anda menemukannya, tetapi mungkin tidak. Jika Anda banyak bekerja dengan bahasa pemrograman maka situasi ini mungkin akrab. Itu adalah "kesalahan ketik" yang akan Anda katakan. Saya akan memperbaiki "kesalahan ketik" yang akan Anda katakan kepada bos Anda.
Dalam
data.table
kami khawatir tentang detail kecil seperti ini. Jadi kami telah melakukan sesuatu yang sederhana untuk menghindari mengetik nama variabel dua kali. Sesuatu yang sangat sederhana.i
dievaluasi dalam bingkaidd
sudah, secara otomatis. Kamu tidak perluwith()
sama sekali.Dari pada
hanya saja
Dan bukannya
hanya saja
Ini perbedaan yang sangat kecil, tetapi mungkin hanya menyelamatkan leher Anda suatu hari. Saat menimbang jawaban yang berbeda untuk pertanyaan ini, pertimbangkan untuk menghitung pengulangan nama variabel sebagai salah satu kriteria Anda dalam memutuskan. Beberapa jawaban memiliki beberapa pengulangan, yang lain tidak.
sumber
subset()
hanya untuk menghindari berulang kali merujuk ke objek yang sama dalam satu panggilan.setorder
fungsi baru juga di sini, karena utas ini adalah tempat kami mengirim semuaorder
tipe dupes.Ada banyak jawaban bagus di sini, tetapi dplyr memberikan satu-satunya sintaks yang dapat saya ingat dengan cepat dan mudah (dan sekarang gunakan sangat sering):
Untuk masalah OP:
sumber
dd[order(-z, b)]
cukup mudah digunakan dan diingat.data.table
merupakan kontribusi besarR
dalam banyak hal juga. Saya kira bagi saya, mungkin bahwa memiliki satu set kurung kurang (atau satu jenis kurung kurang) dalam hal ini mengurangi beban kognitif dengan jumlah yang nyaris tak terlihat.arrange()
sepenuhnya deklaratif,dd[order(-z, b)]
bukan.Paket R
data.table
menyediakan baik cepat dan memori efisien pemesanan data.tables dengan sintaks yang mudah (bagian yang Matt telah menyoroti cukup baik dalam jawabannya ). Telah ada cukup banyak peningkatan dan juga fungsi barusetorder()
sejak saat itu. Dariv1.9.5+
,setorder()
juga berfungsi dengan data.frame .Pertama, kita akan membuat dataset yang cukup besar dan membandingkan metode-metode berbeda yang disebutkan dari jawaban lain dan kemudian mencantumkan fitur-fitur data.table .
Data:
Tolak ukur:
Pengaturan waktu yang dilaporkan berasal dari menjalankan
system.time(...)
fungsi-fungsi ini yang ditunjukkan di bawah ini. Pengaturan waktu ditabulasi di bawah ini (dalam urutan paling lambat hingga tercepat).data.table
'sDT[order(...)]
sintaks adalah ~ 10x lebih cepat dari yang tercepat dari metode lain (dplyr
), sedangkan mengkonsumsi jumlah yang sama memori sebagaidplyr
.data.table
'ssetorder()
adalah ~ 14x lebih cepat dari yang tercepat dari metode lain (dplyr
), saat mengambil hanya 0.4GB memori tambahan .dat
sekarang dalam urutan yang kami butuhkan (karena diperbarui dengan referensi).fitur data.table:
Kecepatan:
pemesanan data.table sangat cepat karena mengimplementasikan pemesanan radix .
Sintaks
DT[order(...)]
dioptimalkan secara internal untuk menggunakan data.table juga memesan cepat. Anda dapat tetap menggunakan sintaks dasar R yang familier tetapi mempercepat prosesnya (dan menggunakan lebih sedikit memori).Penyimpanan:
Sebagian besar waktu, kami tidak memerlukan kerangka data.atau atau data.tabel setelah pemesanan ulang. Artinya, kami biasanya menetapkan hasilnya kembali ke objek yang sama, misalnya:
Masalahnya adalah ini membutuhkan setidaknya dua kali (2x) memori objek asli. Agar memori efisien , data.table juga menyediakan fungsi
setorder()
.setorder()
menata ulang data.tablesby reference
( di tempat ), tanpa membuat salinan tambahan. Ini hanya menggunakan memori ekstra sama dengan ukuran satu kolom.Fitur lainnya:
Mendukung
integer
,logical
,numeric
,character
dan bahkanbit64::integer64
jenis.Di basis R, kita tidak bisa menggunakan
-
vektor karakter untuk mengurutkan berdasarkan kolom itu dalam urutan menurun. Sebaliknya kita harus menggunakan-xtfrm(.)
.Namun, dalam data.table , kita bisa melakukannya, misalnya,
dat[order(-x)]
atausetorder(dat, -x)
.sumber
Dengan fungsi ini (sangat membantu) oleh Kevin Wright , diposting di bagian tips dari wiki R, ini mudah dicapai.
sumber
atau Anda bisa menggunakan paket doBy
sumber
Misalkan Anda memiliki
data.frame
A
dan ingin mengurutkannya menggunakan kolom yang disebutx
urutan menurun. Panggil yang disortirdata.frame
newdata
Jika Anda ingin pesanan naik maka ganti
"-"
dengan yang tidak ada. Anda dapat memiliki sesuatu sepertidi mana
x
danz
beberapa kolom didata.frame
A
. Ini berarti mengurutkandata.frame
A
denganx
menurun,y
naik danz
turun.sumber
jika SQL datang secara alami kepada Anda,
sqldf
paket menanganiORDER BY
seperti yang dimaksudkan Codd.sumber
Atau, menggunakan paket Deducer
sumber
Menanggapi komentar yang ditambahkan dalam OP untuk cara menyortir secara terprogram:
Menggunakan
dplyr
dandata.table
dplyr
Cukup gunakan
arrange_
, yang merupakan versi Evaluasi Standar untukarrange
.info lebih lanjut di sini: https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html
Lebih baik menggunakan rumus karena juga menangkap lingkungan untuk mengevaluasi ekspresi
tabel data
sumber
Saya belajar
order
dengan contoh berikut yang kemudian membingungkan saya untuk waktu yang lama:Satu-satunya alasan contoh ini berfungsi adalah karena
order
disortir olehvector Age
, bukan oleh kolom yang disebutkanAge
dalamdata frame data
.Untuk melihat ini, buat bingkai data yang identik menggunakan
read.table
dengan nama kolom yang sedikit berbeda dan tanpa menggunakan salah satu dari vektor di atas:Struktur garis di atas
order
tidak lagi berfungsi karena tidak ada vektor bernamaage
:Baris berikut berfungsi karena
order
mengurutkan pada kolomage
dimy.data
.Saya pikir ini layak diposkan mengingat betapa bingungnya saya dengan contoh ini sejak lama. Jika posting ini dianggap tidak sesuai untuk utas, saya dapat menghapusnya.
EDIT: 13 Mei 2014
Di bawah ini adalah cara umum menyortir bingkai data dengan setiap kolom tanpa menentukan nama kolom. Kode di bawah ini menunjukkan cara menyortir dari kiri ke kanan atau dari kanan ke kiri. Ini berfungsi jika setiap kolom numerik. Saya belum mencoba dengan kolom karakter yang ditambahkan.
Saya menemukan
do.call
kode satu atau dua bulan yang lalu di sebuah posting lama di situs yang berbeda, tetapi hanya setelah pencarian yang luas dan sulit. Saya tidak yakin bisa memindahkan pos itu sekarang. Utas saat ini adalah hit pertama untuk memesandata.frame
inR
. Jadi, saya pikir versi saya yang diperluas darido.call
kode asli itu mungkin berguna.sumber
require(data.table); my.dt <- data.table(my.data); my.dt[order(age)]
Ini berfungsi karena nama kolom tersedia di dalam kurung [].data.frame
baik untuk menggunakanwith
atau$
.do.call
ini membuat pekerjaan singkat menyortir bingkai data multicolumn. Cukupdo.call(sort, mydf.obj)
dan semacam kaskade yang indah akan didapat.Jawaban Dirk bagus, tetapi jika Anda perlu pengurutan untuk bertahan, Anda ingin menerapkan pengurutan kembali ke nama bingkai data itu. Menggunakan kode contoh:
sumber
Atur () di dplyer adalah opsi favorit saya. Gunakan operator pipa dan beralih dari aspek yang paling tidak penting ke yang paling penting
sumber
Hanya demi kelengkapan, karena tidak banyak yang dikatakan tentang pengurutan berdasarkan nomor kolom ... Dapat dipastikan bahwa itu sering tidak diinginkan (karena urutan kolom bisa berubah, membuka jalan ke kesalahan), tetapi dalam beberapa situasi tertentu (ketika misalnya Anda perlu pekerjaan cepat dilakukan dan tidak ada risiko kolom mengubah pesanan), itu mungkin hal yang paling masuk akal untuk dilakukan, terutama ketika berhadapan dengan sejumlah besar kolom.
Dalam hal ini,
do.call()
datanglah untuk menyelamatkan:sumber
Demi kelengkapan: Anda juga dapat menggunakan
sortByCol()
fungsi dariBBmisc
paket:Perbandingan kinerja:
sumber
data.frame
Seperti halnya penyortir kartu mekanis dahulu kala, pertama urutkan berdasarkan kunci yang paling tidak signifikan, lalu yang paling signifikan berikutnya, dll. Tidak diperlukan pustaka, bekerja dengan sejumlah kunci dan kombinasi tombol mana pun yang naik dan turun.
Sekarang kita siap melakukan kunci yang paling signifikan. Penyortiran stabil, dan ikatan apa pun dalam kunci paling signifikan telah dipecahkan.
Ini mungkin bukan yang tercepat, tetapi tentu saja sederhana dan dapat diandalkan
sumber
Alternatif lain, menggunakan
rgr
paket:sumber
Saya berjuang dengan solusi di atas ketika saya ingin mengotomatiskan proses pemesanan saya untuk n kolom, yang nama kolomnya bisa berbeda setiap kali. Saya menemukan fungsi super bermanfaat dari
psych
paket untuk melakukan ini secara langsung:dimana
columnIndices
indeks dari satu atau lebih kolom, dalam urutan di mana Anda ingin mengurutkannya. Informasi lebih lanjut di sini:dfOrder berfungsi dari paket 'psych'
sumber