Bir data.frame veya matris kullanmalı mıyım?


152

Ne zaman a kullanılmalı data.frame, ne zaman a kullanılmalıdır matrix?

Her ikisi de verileri dikdörtgen biçiminde tutar, bu nedenle bazen belirsizdir.

Hangi veri türünün ne zaman kullanılacağına dair genel kurallar var mı?


Bir matris genellikle belirli bir veri türüne daha uygun olabilir, ancak adı geçen matrisi analiz etmek için kullanmak istediğiniz paket bir veri çerçevesi beklerse, her zaman gereksiz yere dönüştürmeniz gerekir. Hangi paketin hangi paketi kullandığını hatırlamanın bir yolu olmadığını düşünüyorum.
xApple

Yanıtlar:


176

Cevabın bir kısmı zaten sorunuzda yer alıyor: Sütunların (değişkenlerin) farklı türlerde olması bekleniyorsa (sayısal / karakter / mantıksal vb.) Veri çerçeveleri kullanırsınız. Matrisler aynı türdeki veriler içindir.

Sonuç olarak, seçim matrisi / data.frame yalnızca aynı türde verileriniz varsa sorunludur.

Cevap data.frame / matrix'deki verilerle ne yapacağınıza bağlıdır. Diğer işlevlere geçirilecekse, bu işlevlerin bağımsız değişkenlerinin beklenen türü seçimi belirler.

Ayrıca:

Matrisler bellekte daha verimlidir:

m = matrix(1:4, 2, 2)
d = as.data.frame(m)
object.size(m)
# 216 bytes
object.size(d)
# 792 bytes

Herhangi bir doğrusal cebir tipi işlem yapmayı planlıyorsanız, matrisler bir zorunluluktur.

Veri çerçeveleri sütunlarına sık sık ada göre başvuruyorsanız (compact $ operatörü aracılığıyla) daha kullanışlıdır.

Veri çerçeveleri ayrıca, her sütuna ayrı ayrı biçimlendirme uygulayabileceğiniz için tablo bilgilerini raporlamak (yazdırmak) için IMHO'dan daha iyidir.


5
Bu yanıta ekleyeceğim bir şey, grafikler yapmak için ggplot2 paketini kullanmayı planlıyorsanız, ggplot2'nin matrislerle değil yalnızca data.frames ile çalıştığıdır. Dikkat etmemiz gereken birşey!
Bajcz

77

@Michal tarafından belirtilmeyen bir şey, sadece eşdeğer veri çerçevesinden daha küçük bir matris değil, matrislerin kullanılması kodunuzu veri çerçevelerini kullanmaktan çok daha verimli hale getirebilir, çoğu zaman oldukça önemlidir. Dahili olarak, birçok R fonksiyonunun veri çerçevelerindeki matris verilerine zorlanmasının bir nedeni budur.

Veri çerçeveleri genellikle çok daha uygundur; her zaman etrafta duran sadece atomik veri parçaları yoktur.

Bir karakter matrisine sahip olabileceğinizi unutmayın; R'de bir matris oluşturmak için sadece sayısal verilere sahip olmanız gerekmez.

Bir veri çerçevesini bir matrise data.matrix()dönüştürürken, faktörleri iç düzeylere dayalı olarak sayısal değerlere dönüştürerek uygun şekilde işleyen bir işlev olduğunu unutmayın . Üzerinden baskı yapmak as.matrix(), faktör etiketlerinden herhangi biri sayısal değilse bir karakter matrisine neden olur. Karşılaştırmak:

> 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

Genellikle sayısal değişkenlerden daha fazlasına sahip olduğum için veri analizi görevlerim için neredeyse her zaman bir veri çerçevesi kullanırım. Paketler için işlevleri kodladığımda, neredeyse her zaman matrise zorlar ve sonuçları bir veri çerçevesi olarak biçimlendiririm. Bunun nedeni veri çerçevelerinin uygun olmasıdır.


Ben de data.matrix () ve as.matrix () arasındaki farkı merak ediyorum. Onları ve programlama konusundaki ipuçlarını netleştirdiğiniz için teşekkürler.
mikrop

@Gavin Simpson paylaştığınız için teşekkürler! 1-6'dan af'a nasıl dönüleceği hakkında biraz daha bilgi verebilir misiniz?
YJZ

1
@ YZhang Her bir faktör için etiketleri ve matrisin hangi sütunlarının faktör olduğunu belirten mantıksal bir vektör saklamanız gerekir. Daha sonra, yalnızca faktör olan sütunları doğru etiketlerle tekrar faktörlere dönüştürmek nispeten önemsiz olacaktır. Yorumlar kod için iyi yerler değildir, bu nedenle Q'nun daha önce sorulup yanıtlanmadığını ve cevaplanmadığını ve yeni bir soru sormadığına bakın.
Gavin Simpson

47

@Michal: Matrisler gerçekten hafızada daha verimli değildir:

m <- matrix(1:400000, 200000, 2)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 1600776 bytes

... çok sayıda sütununuz yoksa:

m <- matrix(1:400000, 2, 200000)
d <- data.frame(m)
object.size(m)
# 1600200 bytes
object.size(d)
# 22400568 bytes

bellek verimliliği argümanı gerçekten data.framessütun türlerine göre daha fazla esneklik sunmakla ilgilidir. data.frame(a = rnorm(1e6), b = sample(letters, 1e6, TRUE))bellekte matrixtür zorlama nedeniyle sürümden çok daha küçük (hızlı hesaplama ile 6x) olacaktır .
MichaelChirico

9

Matris aslında ek yöntemlere sahip bir vektördür. while data.frame bir listedir. Fark vektör ve listeye düşüyor. hesaplama verimliliği için, matris ile sopa. Gerekirse data.frame kullanma.


3
Hmm, bir matris, boyutlara sahip bir vektördür, yöntemlerin nereden geldiğini görmüyorum?
Gavin Simpson

0

Matrisler ve veri çerçeveleri dikdörtgen 2B dizilerdir ve satırlar ve sütunlar tarafından heterojen olabilir . Bazı yöntemleri ve özellikleri paylaşırlar, ancak hepsini paylaşmazlar.

Örnekler:

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

İkisi arasındaki verimlilik farkını daha fazla vurgulayamıyorum! DF'lerin özellikle bazı veri analizi durumlarında daha uygun olduğu doğru olsa da, heterojen verilere de izin verir ve bazı kütüphaneler yalnızca bunları kabul eder, ancak belirli bir görev için bir defalık kod yazmadıkça bunların hepsi ikincildir.

Sana bir örnek vereyim. MCMC yönteminin 2B yolunu hesaplayacak bir işlev vardı. Temel olarak, bu bir başlangıç ​​noktası (x, y) alır ve her adımda yeni bir nokta (x, y) bulmak için belirli bir algoritmayı yineleyerek, tüm yolu bu şekilde oluşturur. Algoritma oldukça karmaşık bir fonksiyonun hesaplanmasını ve her bir yinelemede bazı rastgele değişkenlerin üretilmesini içerir, bu yüzden 12 saniye boyunca çalıştığında her adımda ne kadar şey yaptığını göz önüne aldığımda iyi olduğunu düşündüm. Bununla birlikte, fonksiyon, 3 sütunlu bir veri çerçevesindeki objektif bir fonksiyonun değeri ile birlikte inşa edilen yoldaki tüm noktaları topladı. Yani, 3 sütun o kadar büyük değildir ve adım sayısı da makul 10.000'den fazlaydı (bu tür problemlerde 1.000.000 uzunluğundaki yollar tipiktir, bu yüzden 10.000 hiçbir şey değildir). DF 10 düşündüm, 000x3 kesinlikle sorun değil. Bir DF'nin kullanılmasının nedeni basittir. İşlevi çağırdıktan sonra, ortaya çıkan (x, y) -yolunu çizmek için ggplot () çağrıldı. Ve ggplot () bir matrisi kabul etmez.

Daha sonra, meraktan bir noktada, bir matristeki yolu toplama işlevini değiştirmeye karar verdim. Memnuniyetle DF'lerin ve matrislerin sözdizimi benzerdir, tek yaptığım df'yi data.frame olarak belirten çizgiyi bir matris olarak başlatan birine değiştirmekti. Burada ayrıca, ilk kodda DF'nin son boyuta sahip olması için başlatıldığını belirtmeliyim, bu nedenle daha sonra fonksiyonun kodunda sadece yeni değerler önceden ayrılmış alanlara kaydedildi ve yeni satırlar ekleme ek yükü yoktu. DF. Bu, karşılaştırmayı daha adil hale getirir ve işlevde başka bir şey yeniden yazmam gerekmediği için işimi de kolaylaştırdı. Gereken boyutta bir data.frame'in ilk tahsisinden aynı boyuttaki bir matrise sadece bir satır değişir. Fonksiyonun yeni sürümünü ggplot () 'a uyarlamak için, şimdi döndürülen matrisi bir verilere dönüştürdüm.

Kodu tekrar çalıştırdıktan sonra sonuca inanamadım. Kod bir saniyenin bir kısmında çalışır! Yaklaşık 12 saniye yerine. Ve yine, 10.000 yineleme sırasındaki fonksiyon sadece bir DF'de (ve şimdi bir matristeki) zaten tahsis edilmiş boşluklara değerler okur ve yazar. Ve bu fark aynı zamanda makul (veya oldukça küçük) boyut olan 10000x3 içindir.

Bu nedenle, bir DF kullanmanın tek nedeni onu ggplot () gibi bir kütüphane işleviyle uyumlu hale getirmekse, son anda her zaman bir DF'ye dönüştürebilirsiniz - uygun gördüğünüz kadar matrislerle çalışın. Öte yandan, DF kullanmak için, matrislerden DF'lere ve geriye doğru sürekli dönüşüm gerektiren bazı veri analiz paketlerini kullanmak gibi daha önemli bir neden varsa veya yoğun hesaplamaları kendiniz yapmaz ve sadece standart kullanırsınız paketleri (birçoğu aslında bir DF'yi bir matrise dahili olarak dönüştürür, işlerini yapar ve sonra sonucu geri dönüştürür - böylece sizin için tüm verimlilik işlerini yaparlar) ya da tek seferlik bir iş yaparlar. DF'lerle daha rahat, o zaman verimlilik konusunda endişelenmemelisiniz.

Veya daha pratik başka bir kural: OP gibi bir sorunuz varsa, matrisler kullanın, böylece DF'leri yalnızca böyle bir sorunuz olmadığında kullanırsınız (çünkü zaten DF'leri kullanmanız gerektiğini biliyorsunuz veya kod bir kerelik vb.Gibi gerçekten umursamıyorum).

Ancak genel olarak bu verimlilik noktasını daima bir öncelik olarak göz önünde bulundurun.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.