"[" Neden "alt kümeden" daha iyidir?


400

Bir data.frame, yani belirli koşulları karşılayan satırları ayıklamak gerektiğinde, ben subsetişlevi kullanmayı tercih :

subset(airquality, Month == 8 & Temp > 90)

[Fonksiyondan ziyade :

airquality[airquality$Month == 8 & airquality$Temp > 90, ]

Tercihimin iki ana nedeni var:

  1. Kodun soldan sağa doğru daha iyi okunduğunu görüyorum. R hakkında hiçbir şey bilmeyen insanlar bile subsetyukarıdaki ifadenin ne yaptığını söyleyebilirdi .

  2. Sütunlar selectifadede değişkenler olarak adlandırılabildiğinden , birkaç tuş vuruşunu kaydedebilirim. Yukarıdaki örneğimde, yalnızca bir airqualitykez subset, ancak üç kez yazmak zorunda kaldım [.

Bu yüzden mutlu oluyordum, subsether yerde kullanıyordum çünkü daha kısa ve daha iyi okuyor, hatta R kodlayıcılarıma güzelliğini savundu. Ama dün dünyam parçalandı. subsetBelgeleri okurken bu bölüme dikkat ediyorum:

Uyarı

Bu, etkileşimli olarak kullanılması amaçlanan bir kolaylık işlevidir. Programlama için, [gibi standart alt kümeleme işlevlerini kullanmak daha iyidir ve özellikle bağımsız değişken alt kümesinin standart dışı değerlendirmesinin beklenmedik sonuçları olabilir.

Birisi yazarların ne anlama geldiğini açıklığa kavuşturabilir mi?

İlk olarak, " etkileşimli kullanım için " ne anlama geliyorlar ? BATCH modunda çalıştırılan bir komut dosyasının aksine etkileşimli bir oturumun ne olduğunu biliyorum, ancak ne fark etmesi gerektiğini anlamıyorum.

O zaman, lütfen “ argüman alt kümesinin standart dışı değerlendirmesini ” ve neden tehlikeli olduğunu açıklayabilir misiniz , belki bir örnek verebilir misiniz ?


14
Kullanmak biraz daha az (ancak somun alt kümeden daha az),with(airquality, airquality[Month == 8 & Temp > 90, ])
Tyler Rinker

7
Ayrıca 'The R Inferno' Cirlces
Patrick Burns

9
Bunun yerine data.table'ı deneyin, varsayılan sözdizimi hava kalitesi gibidir [Month == 8 & Temp> 90,] - çok okunabilir ve çok daha hızlı.
Stian Håklev

3
TAMAM. alt kümenin kullanımı kötüyse - peki [vs. dplyr :: filter ()?
userJT

4
Merak edenler dplyr::filteriçin de aynı problem var. Yani, ortamın bu ada sahip bir değişkeni varsa, veri çerçevesindeki değişken yerine onu kullanır. Hata ayıklamayı karıştırır!
Deleet

Yanıtlar:


241

Bu soru, @James tarafından yapılan yorumlarda, Hadley Wickham'ın [ve buradakisubset işlevlerin ] tehlikeleri hakkında mükemmel bir açıklamaya işaret ederek iyi cevaplanmıştır . Git oku!

Biraz uzun bir okuma, bu yüzden Hadley'nin "neyin yanlış gidebileceği?"

Hadley aşağıdaki örneği önermektedir: varsayalım, aşağıdaki işlevleri kullanarak bir veri çerçevesini alt kümesi ayarlamak ve yeniden sıralamak istiyoruz:

scramble <- function(x) x[sample(nrow(x)), ]

subscramble <- function(x, condition) {
  scramble(subset(x, condition))
}

subscramble(mtcars, cyl == 4)

Bu hatayı döndürür:

Eval hatası (expr, envir, enc): 'cyl' nesnesi bulunamadı

çünkü R artık 'cyl' adlı nesneyi nerede bulacağını “bilemez”. Ayrıca, tesadüfen küresel ortamda 'cyl' adı verilen bir nesne varsa meydana gelebilecek gerçekten tuhaf şeylere dikkat çekiyor:

cyl <- 4
subscramble(mtcars, cyl == 4)

cyl <- sample(10, 100, rep = T)
subscramble(mtcars, cyl == 4)

(Koşun ve kendiniz görün, oldukça çılgın.)


2
Açıklığa kavuşturmak için yeni başlayanlar soruları alabilir miyim? subset(mtcars, cyl == 4)(En üst düzeyde) yazdığımızda , R nerede silindir arar? Aktarılan mtcarsnesneye bakarsa subset(), başka bir fonksiyonun içinde cylolsa bile bulamamalıdır scramble, çünkü mtcarshala ona aktarılıyor mu? Sorum mantıklı değilse, R'nin neden bulamadığını daha ayrıntılı bir şekilde açıklayabilirsiniz cyl. Teşekkürler!
Heisenberg

4
@Anh İçeride subset.data.frame, o noktada değerlendirmeye çalıştığımız şey sadece condition. Bu mevcut değil mtcars. Bu yüzden doğru olarak değerlendirilmesini sağlamak için subset.data.framekullanır . Ama sonra çevreleyen çerçeveye geri döndük ve şimdi R aradığında artık içine bakmıyor . Kullanmasaydık hiç bir şey işe yaramazdı. enclos = parent.frame()conditioncyl == 4cylmtcarsenclossubset(mtcars,cyl == a)
joran

kimse subset () 'in neden sahnelerin arkasındaki daha hızlı ve daha güvenli [,] yöntemi uygulamadığını biliyor mu?
Bjorks bir numaralı fan

1
@MikePalmice Var. Son satırı subset.data.frameolan x[r, vars, drop = drop]. Sorun, alıntılanmamış subsetve selectargümanlardan geçerli olarak geçebileceğiniz bir şeye nasıl ulaşılacağıdır [.data.frame.
joran

@ joran anladı, teşekkürler. yerine dplyr filtresini kullanıp kullanmayacağınızı nasıl düşünüyorsunuz []?
Bjorks bir numaralı fan

30

Ayrıca [daha hızlı:

require(microbenchmark)        
microbenchmark(subset(airquality, Month == 8 & Temp > 90),airquality[airquality$Month == 8 & airquality$Temp > 90,])
    Unit: microseconds
                                                           expr     min       lq   median       uq     max neval
                     subset(airquality, Month == 8 & Temp > 90) 301.994 312.1565 317.3600 349.4170 500.903   100
     airquality[airquality$Month == 8 & airquality$Temp > 90, ] 234.807 239.3125 244.2715 271.7885 340.058   100

36
Evet ve hayır. Bence gördüğünüz zaman farkı iki şeyden kaynaklanıyor. 1) küçük (<100 mikrosaniye) ek yük ve 2) subsetaksine [filtrenin değerlendirildiği satırları kaldırır NA. Bunu yapın ve "oldukça" karşılaştırıldığında her ikisinin de hızlı olduğunu göreceksiniz:x <- do.call(rbind, rep(list(airquality), 100)); microbenchmark(subset(x, Month == 8 & Temp > 90),{ i <- x$Month == 8 & x$Temp > 90; x[!is.na(i) & i ,] })
flodel
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.