Kapan seseorang harus menggunakan a data.frame
, dan kapan lebih baik menggunakan matrix
?
Keduanya menyimpan data dalam format persegi panjang, jadi terkadang tidak jelas.
Apakah ada aturan umum praktis kapan harus menggunakan tipe data apa?
Kapan seseorang harus menggunakan a data.frame
, dan kapan lebih baik menggunakan matrix
?
Keduanya menyimpan data dalam format persegi panjang, jadi terkadang tidak jelas.
Apakah ada aturan umum praktis kapan harus menggunakan tipe data apa?
Jawaban:
Bagian dari jawaban sudah terkandung dalam pertanyaan Anda: Anda menggunakan bingkai data jika kolom (variabel) dapat diharapkan dari tipe yang berbeda (numerik / karakter / logis dll.). Matriks adalah untuk data dari tipe yang sama.
Akibatnya, matriks pilihan / data.frame hanya bermasalah jika Anda memiliki data dengan tipe yang sama.
Jawabannya tergantung pada apa yang akan Anda lakukan dengan data dalam data.frame / matrix. Jika akan diteruskan ke fungsi lain maka jenis argumen yang diharapkan dari fungsi ini menentukan pilihan.
Juga:
Matriks lebih hemat memori:
m = matrix(1:4, 2, 2)
d = as.data.frame(m)
object.size(m)
# 216 bytes
object.size(d)
# 792 bytes
Matriks adalah suatu keharusan jika Anda berencana untuk melakukan segala jenis operasi aljabar linier.
Frame data lebih nyaman jika Anda sering merujuk ke kolomnya dengan nama (melalui operator $ compact).
Frame data juga IMHO lebih baik untuk melaporkan (mencetak) informasi tabular karena Anda dapat menerapkan pemformatan ke setiap kolom secara terpisah.
Sesuatu yang tidak disebutkan oleh @Michal adalah bahwa tidak hanya sebuah matriks lebih kecil dari bingkai data yang setara, menggunakan matriks dapat membuat kode Anda jauh lebih efisien daripada menggunakan bingkai data, sering kali sangat demikian. Itulah salah satu alasan mengapa secara internal, banyak fungsi R akan memaksa data matriks yang ada dalam bingkai data.
Kerangka data seringkali jauh lebih nyaman; seseorang tidak selalu hanya memiliki kumpulan data atom yang ada di sekitarnya.
Perhatikan bahwa Anda dapat memiliki matriks karakter; Anda tidak hanya harus memiliki data numerik untuk membangun matriks dalam R.
Dalam mengonversi kerangka data ke matriks, perhatikan bahwa ada data.matrix()
fungsi, yang menangani faktor secara tepat dengan mengonversinya menjadi nilai numerik berdasarkan level internal. Pemaksaan via as.matrix()
akan menghasilkan matriks karakter jika salah satu label faktor adalah non-numerik. Membandingkan:
> head(as.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
a B
[1,] "a" "A"
[2,] "b" "B"
[3,] "c" "C"
[4,] "d" "D"
[5,] "e" "E"
[6,] "f" "F"
> head(data.matrix(data.frame(a = factor(letters), B = factor(LETTERS))))
a B
[1,] 1 1
[2,] 2 2
[3,] 3 3
[4,] 4 4
[5,] 5 5
[6,] 6 6
Saya hampir selalu menggunakan bingkai data untuk tugas analisis data saya karena saya sering memiliki lebih dari sekedar variabel numerik. Ketika saya kode fungsi untuk paket, saya hampir selalu memaksa ke matriks dan kemudian memformat hasil kembali sebagai bingkai data. Ini karena bingkai data nyaman.
@Michal: Matriks tidak benar-benar lebih hemat memori:
m <- matrix(1:400000, 200000, 2)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 1600776 bytes
... kecuali Anda memiliki banyak kolom:
m <- matrix(1:400000, 2, 200000)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 22400568 bytes
data.frames
menawarkan lebih banyak fleksibilitas daripada jenis kolom. data.frame(a = rnorm(1e6), b = sample(letters, 1e6, TRUE))
akan jauh lebih kecil (6x dengan perhitungan cepat saya) di memori daripada matrix
versi karena tipe paksaan.
Matriks sebenarnya adalah vektor dengan metode tambahan. sedangkan data.frame adalah daftar. Perbedaannya adalah ke daftar vektor vs. untuk efisiensi perhitungan, gunakan matriks. Menggunakan data.frame jika Anda harus.
Matriks dan bingkai data adalah array 2D persegi panjang dan dapat heterogen dengan baris dan kolom . Mereka berbagi beberapa metode dan properti, tetapi tidak semua.
Contoh:
M <- list(3.14,TRUE,5L,c(2,3,5),"dog",1i) # a list
dim(M) <- c(2,3) # set dimensions
print(M) # print result
# [,1] [,2] [,3]
# [1,] 3.14 5 "dog"
# [2,] TRUE Numeric,3 0+1i
DF <- data.frame(M) # a data frame
print(DF) # print result
# X1 X2 X3
# 1 3.14 5 dog
# 2 TRUE 2, 3, 5 0+1i
M <- matrix(c(1,1,1,1,2,3,1,3,6),3) # a numeric matrix
DF <- data.frame(M) # a all numeric data frame
solve(M) # obtains inverse matrix
solve(DF) # obtains inverse matrix
det(M) # obtains determinant
det(DF) # error
Saya tidak bisa lebih menekankan perbedaan efisiensi antara keduanya! Memang benar bahwa DF lebih nyaman dalam beberapa kasus analisis data khusus, mereka juga memungkinkan data heterogen, dan beberapa perpustakaan hanya menerimanya, ini semua benar-benar sekunder kecuali jika Anda menulis kode satu kali untuk tugas tertentu.
Biarkan saya memberi Anda sebuah contoh. Ada fungsi yang akan menghitung jalur 2D dari metode MCMC. Pada dasarnya, ini berarti kita mengambil titik awal (x, y), dan iterasi algoritma tertentu untuk menemukan titik baru (x, y) pada setiap langkah, membangun cara ini seluruh jalur. Algoritme melibatkan menghitung fungsi yang cukup kompleks dan menghasilkan beberapa variabel acak pada setiap iterasi, jadi ketika dijalankan selama 12 detik saya pikir tidak masalah mengingat berapa banyak hal yang dilakukannya pada setiap langkah. Yang sedang berkata, fungsi mengumpulkan semua titik di lintasan yang dibangun bersama dengan nilai fungsi obyektif dalam bingkai data 3-kolom. Jadi, 3 kolom tidak terlalu besar, dan jumlah langkahnya juga lebih dari 10.000 yang masuk akal (dalam masalah semacam ini panjang jalur 1.000.000 adalah tipikal, jadi 10.000 bukan apa-apa). Jadi, saya pikir DF 10, 000x3 jelas bukan masalah. Alasan DF digunakan adalah sederhana. Setelah memanggil fungsi, ggplot () dipanggil untuk menggambar (x, y) -path yang dihasilkan. Dan ggplot () tidak menerima matriks.
Kemudian, pada suatu titik karena penasaran saya memutuskan untuk mengubah fungsi untuk mengumpulkan path dalam sebuah matriks. Dengan senang hati sintaks DF dan matriksnya serupa, yang saya lakukan hanyalah mengubah garis yang menentukan df sebagai data.frame menjadi satu yang menginisialisasi sebagai matriks. Di sini saya juga perlu menyebutkan bahwa dalam kode awal DF diinisialisasi untuk memiliki ukuran akhir, jadi kemudian dalam kode fungsi hanya nilai-nilai baru dicatat ke dalam ruang yang sudah dialokasikan, dan tidak ada overhead menambahkan baris baru ke DF. Ini membuat perbandingan lebih adil, dan itu juga membuat pekerjaan saya lebih sederhana karena saya tidak perlu menulis ulang apa pun lebih lanjut dalam fungsi. Hanya satu perubahan baris dari alokasi awal data. Bingkai ukuran yang diperlukan untuk matriks dengan ukuran yang sama. Untuk mengadaptasi versi baru dari fungsi ke ggplot (), saya mengonversikan matriks yang sekarang dikembalikan ke data.
Setelah saya jalankan kembali kode saya tidak bisa percaya hasilnya. Kode berjalan dalam sepersekian detik! Alih-alih sekitar 12 detik. Dan lagi, fungsi selama 10.000 iterasi hanya membaca dan menulis nilai ke ruang yang sudah dialokasikan dalam DF (dan sekarang dalam matriks). Dan perbedaan ini juga untuk ukuran yang wajar (atau agak kecil) 10000x3.
Jadi, jika satu-satunya alasan Anda menggunakan DF adalah untuk membuatnya kompatibel dengan fungsi pustaka seperti ggplot (), Anda selalu dapat mengonversinya ke DF pada saat terakhir - bekerja dengan matriks sejauh Anda merasa nyaman. Jika di sisi lain ada alasan yang lebih substansial untuk menggunakan DF, seperti Anda menggunakan beberapa paket analisis data yang akan membutuhkan transformasi konstan dari matriks ke DF dan kembali, atau Anda tidak melakukan perhitungan intensif sendiri dan hanya menggunakan standar paket (banyak dari mereka benar-benar secara internal mengubah DF ke matriks, melakukan pekerjaan mereka, dan kemudian mengubah hasilnya kembali - sehingga mereka melakukan semua pekerjaan efisiensi untuk Anda), atau melakukan pekerjaan satu kali sehingga Anda tidak peduli dan merasa lebih nyaman dengan DF, maka Anda tidak perlu khawatir tentang efisiensi.
Atau aturan lain yang lebih praktis: jika Anda memiliki pertanyaan seperti di OP, gunakan matriks, jadi Anda akan menggunakan DF hanya ketika Anda tidak memiliki pertanyaan seperti itu (karena Anda sudah tahu Anda harus menggunakan DF, atau karena Anda memiliki tidak terlalu peduli karena kodenya satu kali dll).
Tetapi secara umum menjaga titik efisiensi ini selalu dalam pikiran sebagai prioritas.