Haruskah saya menggunakan data.frame atau matriks?


152

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?


Seringkali sebuah matriks dapat lebih cocok untuk jenis data tertentu, tetapi jika paket yang ingin Anda gunakan untuk menganalisis matriks tersebut mengharapkan bingkai data, Anda harus selalu mengubahnya secara tidak perlu. Saya pikir tidak ada cara untuk menghindari mengingat paket mana yang menggunakan.
xApple

Jawaban:


176

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.


5
Satu hal yang akan saya tambahkan ke jawaban ini adalah bahwa jika Anda berencana menggunakan paket ggplot2 untuk membuat grafik, ggplot2 hanya berfungsi dengan data.frame dan bukan matriks. Hanya sesuatu yang harus diperhatikan!
Bajcz

77

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.


Saya telah bertanya-tanya perbedaan antara data.matrix () dan as.matrix () juga. Terima kasih untuk memperjelasnya dan tips Anda dalam pemrograman.
microbe

Terima kasih telah berbagi @Gavin Simpson! Bisakah Anda memperkenalkan sedikit lebih banyak tentang bagaimana kembali dari 1-6 ke af?
YJZ

1
@ YZhang Anda harus menyimpan label untuk setiap faktor dan vektor logis yang menunjukkan kolom mana dari matriks yang menjadi faktor. Maka akan relatif sepele untuk mengubah hanya kolom-kolom yang merupakan faktor kembali menjadi faktor dengan label yang benar. Komentar bukanlah tempat yang baik untuk kode, jadi lihat apakah Q telah ditanyakan & dijawab sebelum dan jika tidak mengajukan pertanyaan baru.
Gavin Simpson

47

@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

argumen efisiensi memori sebenarnya tentang data.framesmenawarkan 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 matrixversi karena tipe paksaan.
MichaelChirico

9

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.


3
Hmm, sebuah matriks adalah vektor dengan dimensi, saya tidak melihat di mana metode itu?
Gavin Simpson

0

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

0

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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.