data.table vs dplyr: biri yaxshi ishni qila oladimi, ikkinchisi qila olmaydi yoki yomon qiladimi?

Umumiy koʻrinish

Men data.table bilan nisbatan tanishman, dplyr bilan unchalik emas. Men ba'zi dplyr vinyetka va SO'da paydo bo'lgan misollarni o'qib chiqdim va hozirgacha mening xulosalar quyidagilar:

  1. data.table va dplyr tezligi bo'yicha solishtirish mumkin, ko'p (ya'ni > 10-100K) guruhlar mavjud bo'lganda va ba'zi boshqa holatlar bundan mustasno (quyida ko'rsatkichlarga qarang)
  2. dplyr sintaksisi yanada qulayroq
  3. dplyr ma'lumotlar bazasining potentsial o'zaro ta'sirini ko'rsatadi (yoki bo'ladi).
  4. Funktsionallik boʻyicha baʼzi kichik farqlar mavjud (quyida “Misollar/foydalanish” ga qarang)

Mening fikrimcha 2. unchalik og'irlik qilmaydi, chunki men u bilan yaxshi tanishman data.table, lekin ikkalasini ham yangi foydalanuvchilar uchun bu katta omil bo'lishini tushunaman. Men qaysi biri intuitivroq ekanligi haqidagi bahsdan qochmoqchiman, chunki bu mening data.table bilan tanish bo'lgan odamning nuqtai nazaridan berilgan maxsus savolim uchun ahamiyatsiz. Men, shuningdek, "intuitivroq" tezroq tahlilga qanday olib kelishi haqida munozaralardan qochishni xohlayman (albatta, to'g'ri, lekin bu erda meni eng ko'p qiziqtiradigan narsa emas).

Savol

Men bilmoqchi bo'lgan narsa:

  1. Paketlar bilan tanish bo'lgan odamlar uchun u yoki bu paket bilan kodlash ancha oson bo'lgan analitik vazifalar bormi (ya'ni, zarur bo'lgan klavishlarni bosish kombinatsiyasi va zarur ezoterizm darajasi, bunda har birining kamroq qismi yaxshi narsa).
  2. Bir paketda boshqasiga nisbatan sezilarli darajada (ya'ni 2x dan ortiq) samaraliroq bajariladigan analitik vazifalar bormi?

Bitta Oxirgi SO savoli meni o‘ylantirdi. Bu biroz ko'proq, chunki shu paytgacha men dplyr data.table da qila oladigan narsadan ko'proq narsani taklif qiladi deb o'ylamagan edim. Mana dplyr yechim (Q oxiridagi ma'lumotlar):

dat %.%
  group_by(name, job) %.%
  filter(job != "Boss" | year == min(year)) %.%
  mutate(cumu_job2 = cumsum(job2))

Bu mening data.table yechimini buzishga urinishimdan ancha yaxshi edi. Ya'ni, yaxshi data.table echimlar ham juda yaxshi (rahmat Jan-Robert, Arun va bu erda e'tibor bering, men eng maqbul echimdan ko'ra bitta bayonotni afzal ko'rdim):

setDT(dat)[,
  .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], 
  by=list(id, job)
]

Ikkinchisining sintaksisi juda ezoterik ko'rinishi mumkin, lekin agar siz data.table ga o'rganib qolgan bo'lsangiz (ya'ni, ba'zi ezoterik fokuslardan foydalanmasangiz) bu juda oddiy.

Ideal holda, men ko'rmoqchi bo'lgan yaxshi misollar: dplyr yoki data.table yo'l ancha ixchamroq yoki ancha yaxshi ishlaydi.

Misollar

Usage
  • dplyr ixtiyoriy qatorlar sonini qaytaradigan guruhlangan operatsiyalarga ruxsat bermaydi (eddi savoli, e'tibor bering: u dplyr 0.5shuningdek, @beginneR @eddining savoliga javobda do yordamida potentsial echimni ko'rsatadi).
  • data.table aylanma ulanishlarni qo‘llab-quvvatlaydi (rahmat @dholstius) shuningdek qo'shilish
  • data.table bir xil asosiy R sintaksisidan foydalangan holda ikkilik qidiruvdan foydalanadigan avtomatik indekslash orqali tezlik uchun DT[col == value] yoki DT[col %in% values] shaklidagi ifodalarni ichki optimallashtiradi. Batafsil ma'lumot va kichik mezon uchun bu yerga qarang.
  • dplyr funksiyalarning standart baholash versiyalarini (masalan, regroup, summarize_each_) taklif etadi, ular dplyr dan dasturiy foydalanishni soddalashtiradi (eslatma: data.table dan dasturiy foydalanish, albatta, mumkin, shunchaki ehtiyotkorlik bilan oʻylash, almashtirish/iqtibos keltirish va h.k., hech boʻlmaganda mening bilishimcha)
Benchmarks

Ma'lumotlar

Bu savol bo'limida ko'rsatgan birinchi misol uchun.

dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane", 
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob", 
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L, 
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L, 
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager", 
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager", 
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L, 
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id", 
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA, 
-16L))

person BrodieG    schedule 29.01.2014    source manba
comment
dplyr ni o'qishda o'xshash yechim: as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]   -  person eddi    schedule 29.01.2014
comment
№1 uchun dplyr va data.table jamoalar sinovlar ustida ishlamoqda, shuning uchun javob bir nuqtada bo'ladi. №2 (sintaksis) imO mutlaqo noto'g'ri, lekin bu aniq fikr hududiga kiradi, shuning uchun men ham yopish uchun ovoz beraman.   -  person eddi    schedule 29.01.2014
comment
@eddi, lekin birida aniq ifodalanishi mumkin bo'lgan muammolar bormi, lekin boshqasi yo'q? Yoki bu sizning fikringizcha, qat'iy uslubmi?   -  person BrodieG    schedule 29.01.2014
comment
Xo'sh, yana imO, (d)plyr da aniqroq ifodalangan muammolar to'plami 0 o'lchoviga ega   -  person eddi    schedule 29.01.2014
comment
@eddi, bu mening umumiy nuqtai nazarim, garchi men buni istisno qilish uchun dplyr ni yaxshi bilmayman va kimdir yaxshi qarshi misol keltira oladimi, deb qiziqdim. Bundan tashqari, data.table formulasini yaxshi soddalashtirish.   -  person BrodieG    schedule 29.01.2014
comment
Bu plyr va data.table haqida soʻragan stackoverflow.com/q/16153947/892313ga juda oʻxshaydi va u ham yopildi. U erda mening javobim nima uchun bu ko'proq ekanligini tushuntiradi.   -  person Brian Diggs    schedule 29.01.2014
comment
@eddi IMHO data.table da aniqroq ifodalangan muammolar to'plami 0 o'lchoviga ega, ammo bu sizning e'tiqodingizga zid emas;)   -  person hadley    schedule 29.01.2014
comment
@hadley :) Bu faqat nol bo'lmagan muammolar to'plamini qamrab olmaydi deb hisoblasangiz, bu izchil bo'ladi; Yana jiddiyroq, menimcha, SO-da paydo bo'ladigan guruh/xulosa/va hokazo savollarning 99 foizini qamrab oluvchi vinyetka (bularning barchasi taxminan 5-10 ta aniq muammolarning juda yaqin reenkarnasyonlari), turli xil ilovalar va ularning mezonlari bilan. ko'p vaqt o'tib ketgan   -  person eddi    schedule 29.01.2014
comment
@eddi Agar data.table va dplyr har bir muammo uchun bir xil darajada ifodalangan deb hisoblasangiz, bu ham izchil. Ko'rsatkichlar unchalik qiziq emas deb o'ylayman, lekin mening nuqtai nazarimdan cran.r-project.org/web/packages/dplyr/vignettes/ eng qiziqarli (men uchun) muammo turlarini qamrab oladi.   -  person hadley    schedule 30.01.2014
comment
@hadley ha, bu muammolarning aksariyat qismini qamrab oladi. Ikkita tezkor sharh - oxirida data.table qo'shilmaydimi? Va (ehtimol, boshqa joyda aytib o'tilganlarni takrorlagan holda) qiziqarliroq ma'lumotlar o'lchamlari haqida nima deyish mumkin (bu erda men qiziqarli deganda bir daqiqadan ko'proq vaqt talab qiladigan narsa deb ta'riflagan bo'lardim - bu odatda odamlar paketlarning mezonlarini o'rganishni boshlashining asosiy sababidir)?   -  person eddi    schedule 30.01.2014
comment
@BrodieG meni sintaksisga nisbatan dplyr va plyr haqida haqiqatan ham bezovta qiladigan va ularning sintaksisini yoqtirmasligimning asosiy sababi shundaki, men juda ko'p (1 dan ortiq o'qing) qo'shimcha funktsiyalarni (nomlar bilan) o'rganishim kerak. buhali hammen uchun mantiqiy emas), ular nima qilishlarini, qanday dalillarni olishlarini va hokazolarni eslang.   -  person eddi    schedule 30.01.2014
comment
@eddi Data.table konversiyalarini yozishdan charchadim. Data.table ekvivalentlarini qo'shgan tortishish so'rovini mamnuniyat bilan qabul qilaman. Algoritmlarning aksariyati O(n) bo'lgani uchun kichik ma'lumotlar o'lchamlariga yopishib oldim, lekin qarshi misollarni ko'rishdan xursand bo'lardim.   -  person hadley    schedule 30.01.2014
comment
@eddi [til-in-cheek] meni data.table sintaksisi bilan bog'liq bir narsa bezovta qiladigan narsa shundaki, men juda ko'p funktsiya argumentlari qanday o'zaro ta'sir qilishini va sirli yorliqlar nimani anglatishini o'rganishim kerak (masalan, .SD). [jiddiy] Menimcha, bu turli odamlarga yoqadigan qonuniy dizayn farqlari   -  person hadley    schedule 30.01.2014
comment
@hadley re .SD va boshqalar - bu adolatli - .SD tushunish uchun menga bir oz vaqt kerak bo'ldi, lekin u erga etib borganimda, men allaqachon ko'p narsalarni qila oldim, shu bilan birga (d)plyr sizga katta to'siqni taqdim etadi.   -  person eddi    schedule 30.01.2014
comment
Bu data.table (hozirda) oddiyroq yechimni taqdim etadigan misol bo'lib ko'rinadi: stackoverflow.com/questions/21295936/   -  person Vincent    schedule 31.01.2014
comment
Bu yerda [stackoverflow.com/questions/21477525/ dplyr va data.table ni solishtirishga misoldir.   -  person danas.zuokas    schedule 31.01.2014
comment
Mana bu taqqoslash jihati, men hozirgina dplyr-ga qo'shilishlar haqidagi so'nggi tvitlarga qo'shimcha nuqtai nazar berish uchun qildim. /data.jadval. HTH.   -  person Arun    schedule 07.05.2014
comment
@Arun, qiziq. Men bu haqda postda qayd qildim.   -  person BrodieG    schedule 07.05.2014
comment
Bu savol S.O.ga ruxsat berilmagani uchun yopilgan deb o'ylaysizmi? Agar u shu yerda saqlanishi kerak bo‘lsa, uni hamjamiyat vikisiga aylantirsam bo‘ladi – men bunga tayyorman. Taqqoslashda hozircha juda kam narsa bor; masalan buyurtma qilingan qo'shilishlar. Javoblarni qo'shishga ruxsat bormi?   -  person Matt Dowle    schedule 24.10.2014
comment
@MattDowle, u yopildi, lekin kimdir uni qayta ochdi. Ehtimol, javoblarga ruxsat berilganmi? Albatta, jamoat vikisiga aylantirilishi mumkin (qanday qilib bilmayman).   -  person BrodieG    schedule 24.10.2014
comment
Rolling qo'shiladi. data.table ularni bajaradi. dplyr yo'q (hali).   -  person dholstius    schedule 05.11.2014
comment
@dholstius, endi ta'kidladi, buni ta'kidlaganingiz uchun tashakkur, men bu haqda o'ylamagan edim. Bu, shuningdek, bir-biriga o'xshash birikmalarni amalga oshirishni kashf qilishimga olib keldi.   -  person BrodieG    schedule 05.11.2014
comment
Menga o'xshaganlardan biriga maslahatim, data.table o'rganishni maslahat beraman, bu standart ma'lumotlar ramkasidan ancha kamroq va ko'p operatsiyalar tezroq. Bu sizni vektoriy fikrlash bilan o'ylashga majbur qiladi (yaxshiroq ishlashga ega). Men buni ma'lumotlar ramkasining yaxshi o'rnini bosuvchi sifatida ko'raman. Sintaksis dastlab intuitiv emas, lekin uni ishlatganingizdan so'ng uni eslab qolish oson. Men dplyrni funktsiyalar to'plami sifatida ko'raman, lekin data.tablean'anaviy ma'lumotlar ramkasidan ancha yaxshi ishlashi va ixcham sintaksisiga ega yangi sinf ob'ekti sifatida.   -  person David Leal    schedule 15.03.2017
comment
@eddi Nega bu iborani i tomonida emas, j-da yozyapsiz?   -  person skan    schedule 16.07.2017
comment
@skan Men buning kontekstini endi eslay olmayman, ehtimol shunga o'xshash o'qishga erishish kerak edi.   -  person eddi    schedule 17.07.2017


Javoblar (4)


Keng qamrovli javob/taqqoslash (muayyan muhimlik tartibida) berish uchun kamida bu jihatlarni qamrab olishimiz kerak: Speed, Memory usage, Syntax va Features.

Mening maqsadim bularning har birini data.table nuqtai nazaridan iloji boricha aniqroq yoritishdir.

Eslatma: agar boshqachasi aniq aytilmagan bo'lsa, dplyr ga murojaat qilib, biz Rcpp yordamida ichki qismlari C++ da joylashgan dplyr ning data.frame interfeysiga murojaat qilamiz.


Ma'lumotlar.jadval sintaksisi o'z shaklida mos keladi - DT[i, j, by]. i, j va by ni birga saqlash dizayn bo'yicha. Tegishli operatsiyalarni birga saqlash orqali u operatsiyalarni tezlik va eng muhimi xotiradan foydalanish uchun osonlik bilan optimallashtirish imkonini beradi, shuningdek, ba'zi kuchli funksiyalarni taqdim etadi. hammasi sintaksisdagi izchillikni saqlagan holda.

1. Tezlik

Savolga bir nechta mezonlar qo'shilgan (asosan guruhlash operatsiyalari bo'yicha) ma'lumotlar jadvali dplyrga qaraganda tezroq bo'ladi, chunki guruhlash uchun guruhlar va/yoki qatorlar soni, shu jumladan Mett tomonidan 10 milliondan 2 milliardgacha bo'lgan guruhlash bo'yicha mezonlari qatorlar (RAMda 100 Gb) 100 - 10 million guruhlarda va turli guruhlash ustunlari, ular ham pandas ni taqqoslaydi. Shuningdek, yangilangan mezonlarni ko‘ring, ular orasida Spark va pydatatable ham bor.

Benchmarklarda ushbu qolgan jihatlarni ham qamrab olsak yaxshi bo'lardi:

  • qatorlar kichik to'plamini o'z ichiga olgan guruhlash operatsiyalari - ya'ni DT[x > val, sum(y), by = z] tipidagi operatsiyalar.

  • yangilash va qo'shilish kabi boshqa operatsiyalarni taqqoslang.

  • Ish vaqtiga qo'shimcha ravishda har bir operatsiya uchun xotira izini ham taqqoslang.

2. Xotiradan foydalanish

  1. #P10#
    #P11#
  2. #P12#
     # sub-assign by reference, updates 'y' in-place
     DT[x >= 1L, y := NA]
    
    #P13#
     # copies the entire 'y' column
     ans <- DF %>% mutate(y = replace(y, which(x >= 1L), NA))
    
    #P14# #P15#
     foo <- function(DT) {
         DT = shallow(DT)          ## shallow copy DT
         DT[, newcol := 1L]        ## does not affect the original DT 
         DT[x > 2L, newcol := 2L]  ## no need to copy (internally), as this column exists only in shallow copied DT
         DT[x > 2L, x := 3L]       ## have to copy (like base R / dplyr does always); otherwise original DT will 
                                   ## also get modified.
     }
    
    #P16#
     bar <- function(DT) {
         DT[, newcol := 1L]        ## old behaviour, original DT gets updated by reference
         DT[x > 2L, x := 3L]       ## old behaviour, update column x in original DT.
     }
    
    #P17#
    #P18#
    #P19#
  3. Qo'shilish paytida jamlash:

    Aytaylik, sizda quyidagi ikkita data.tables mavjud:

     DT1 = data.table(x=c(1,1,1,1,2,2,2,2), y=c("a", "a", "b", "b"), z=1:8, key=c("x", "y"))
     #    x y z
     # 1: 1 a 1
     # 2: 1 a 2
     # 3: 1 b 3
     # 4: 1 b 4
     # 5: 2 a 5
     # 6: 2 a 6
     # 7: 2 b 7
     # 8: 2 b 8
     DT2 = data.table(x=1:2, y=c("a", "b"), mul=4:3, key=c("x", "y"))
     #    x y mul
     # 1: 1 a   4
     # 2: 2 b   3
    

    Va siz x,y ustunlar bo'yicha qo'shilganda DT2 dagi har bir qator uchun sum(z) * mul olishni xohlaysiz. Biz ham qila olamiz:

      1. sum(z) olish uchun DT1 ni yig'ing, 2) birlashmani bajaring va 3) ko'paytiring (yoki)

        ma'lumotlar.jadval usuli

        DT1[, .(z = yig'indi (z)), tugmachali = .(x,y)][DT2][, z := z*mul][]

        dplyr ekvivalenti

        DF1 %›% group_by(x, y) %›% jamlama(z = sum(z)) %›% o‘ngga_qo‘shilish(DF2) %›% mutatsiya(z = z * mul)

      1. hammasini bir marta bajaring (by = .EACHI funksiyasidan foydalanib):

        DT1[DT2, list(z=sum(z) * mul), by = .EACHI]

    Buning qanday afzalligi bor?

    • Oraliq natija uchun xotira ajratishimiz shart emas.

    • Ikki marta guruhlash/xesh qilishimiz shart emas (biri yig‘ish uchun, ikkinchisi esa qo‘shilish uchun).

    • Va bundan ham muhimi, biz bajarmoqchi bo'lgan operatsiya (2) dagi j ga qarab aniq bo'ladi.

    by = .EACHI haqida batafsil tushuntirish uchun ushbu postni tekshiring. Hech qanday oraliq natijalar amalga oshirilmaydi va qo'shilish + yig'ish bir vaqtning o'zida amalga oshiriladi.

    buni ko'rib chiqing, bu va bu haqiqiy foydalanish stsenariylari uchun postlar.

    dplyr-da siz avval qo‘shilishingiz va jamlashingiz yoki jamlashingiz, so‘ngra qo‘shishingiz kerak bo‘ladi, ularning hech biri bir xil emas samarali, xotira jihatidan (bu o'z navbatida tezlikni anglatadi).

  4. Yangilash va qo'shilish:

    Quyida ko'rsatilgan data.table kodini ko'rib chiqing:

     DT1[DT2, col := i.mul]
    

    DT1 ning col ustunini DT2 dan mul bilan DT2 kalit ustuni DT1 ga mos keladigan qatorlarga qo'shadi/yangilaydi. Menimcha, dplyr da bu operatsiyaning aniq ekvivalenti yo'q, ya'ni *_join operatsiyasidan qochmasdan, unga yangi ustun qo'shish uchun butun DT1 ni nusxalash kerak bo'ladi, bu keraksizdir.

    Haqiqiy foydalanish stsenariysi uchun ushbu postni tekshiring.

Xulosa qilib aytganda, optimallashtirishning har bir qismi muhimligini tushunish muhimdir. Greys Xopper aytganidek, Nanosoniyalarga e'tibor bering!

3. Sintaksis

Endi sintaksisni ko'rib chiqamiz. Xedli bu yerda fikr bildirdi:

Ma'lumotlar jadvallari juda tez, lekin menimcha, ularning qisqaligi o'rganishni qiyinlashtiradi va kodni yozganingizdan keyin uni o'qish qiyinroq ...

Men bu fikrni behuda deb bilaman, chunki bu juda subyektiv. sintaksisdagi izchillikniga qarama-qarshi qo'yishga urinib ko'rishimiz mumkin. Biz data.table va dplyr sintaksisini yonma-yon taqqoslaymiz.

Biz quyida ko'rsatilgan soxta ma'lumotlar bilan ishlaymiz:

DT = data.table(x=1:10, y=11:20, z=rep(1:2, each=5))
DF = as.data.frame(DT)
  1. Asosiy yig'ish/yangilash operatsiyalari.

     # case (a)
     DT[, sum(y), by = z]                       ## data.table syntax
     DF %>% group_by(z) %>% summarise(sum(y)) ## dplyr syntax
     DT[, y := cumsum(y), by = z]
     ans <- DF %>% group_by(z) %>% mutate(y = cumsum(y))
    
     # case (b)
     DT[x > 2, sum(y), by = z]
     DF %>% filter(x>2) %>% group_by(z) %>% summarise(sum(y))
     DT[x > 2, y := cumsum(y), by = z]
     ans <- DF %>% group_by(z) %>% mutate(y = replace(y, which(x > 2), cumsum(y)))
    
     # case (c)
     DT[, if(any(x > 5L)) y[1L]-y[2L] else y[2L], by = z]
     DF %>% group_by(z) %>% summarise(if (any(x > 5L)) y[1L] - y[2L] else y[2L])
     DT[, if(any(x > 5L)) y[1L] - y[2L], by = z]
     DF %>% group_by(z) %>% filter(any(x > 5L)) %>% summarise(y[1L] - y[2L])
    
    • data.table sintaksisi ixcham va dplyr juda batafsil. (a) holatda narsalar ko'proq yoki kamroq ekvivalentdir.

    • (b) holatda biz jamlashda dplyr-da filter() dan foydalanishimiz kerak edi. Lekin yangilash paytida biz mantiqni mutate() ichiga o'tkazishimiz kerak edi. Biroq data.table da biz ikkala amalni ham bir xil mantiq bilan ifodalaymiz - x > 2 bo'lgan qatorlarda ishlaymiz, lekin birinchi holatda sum(y) ni oling, ikkinchi holatda esa bu qatorlarni yig'indisi bilan y uchun yangilang.

      DT[i, j, by] shakli mos keladi deganda biz shuni nazarda tutamiz.

    • Xuddi shunday (c) holatida, bizda if-else shart mavjud bo'lganda, biz mantiqni xuddi shunday ham data.table, ham dplyr da ifodalay olamiz. Biroq, agar biz if sharti qanoatlantirilgan qatorlarni qaytarmoqchi bo'lsak va aks holda o'tkazib yuborsak, biz to'g'ridan-to'g'ri summarise() dan foydalana olmaymiz (AFAICT). Avval filter() ni, keyin esa umumlashtirishimiz kerak, chunki summarise() har doim bitta qiymatni kutadi.

      Xuddi shu natijani qaytarsa-da, bu erda filter() dan foydalanish haqiqiy operatsiyani kamroq ravshan qiladi.

      Birinchi holatda ham filter() dan foydalanish juda mumkin bo'lishi mumkin (menga aniq ko'rinmaydi), lekin mening fikrimcha, biz bunga majbur emasmiz.

  2. Bir nechta ustunlarda yig'ish / yangilash

     # case (a)
     DT[, lapply(.SD, sum), by = z]                     ## data.table syntax
     DF %>% group_by(z) %>% summarise_each(funs(sum)) ## dplyr syntax
     DT[, (cols) := lapply(.SD, sum), by = z]
     ans <- DF %>% group_by(z) %>% mutate_each(funs(sum))
    
     # case (b)
     DT[, c(lapply(.SD, sum), lapply(.SD, mean)), by = z]
     DF %>% group_by(z) %>% summarise_each(funs(sum, mean))
    
     # case (c)
     DT[, c(.N, lapply(.SD, sum)), by = z]     
     DF %>% group_by(z) %>% summarise_each(funs(n(), mean))
    
    • (a) holatida kodlar ko'proq yoki kamroq ekvivalentdir. data.table lapply() tanish asosiy funksiyasidan foydalanadi, dplyr esa funs() ga bir qator funktsiyalar bilan birga *_each() ni kiritadi.

    • data.table ning := ustun nomlarini ko'rsatishni talab qiladi, dplyr esa uni avtomatik ravishda yaratadi.

    • (b) holida dplyr sintaksisi nisbatan sodda. Bir nechta funksiyalar bo'yicha jamlash/yangilanishlarni yaxshilash data.table ro'yxatida.

    • Agar (c) bo'lsa, dplyr bir marta emas, balki ko'p sonli ustunlarni n() qaytaradi. Data.table da biz qilishimiz kerak bo'lgan narsa j ro'yxatini qaytarishdir. Ro'yxatning har bir elementi natijada ustunga aylanadi. Shunday qilib, biz yana bir bor tanish bo'lgan c() tayanch funktsiyasidan .N ni list ni qaytaradigan list ga birlashtirish uchun foydalanishimiz mumkin.

    Eslatma: Yana bir bor, data.table da j ro'yxatini qaytarishimiz kifoya. Ro'yxatning har bir elementi natijada ustunga aylanadi. Buni amalga oshirish uchun c(), as.list(), lapply(), list() va hokazo... asosiy funktsiyalardan foydalanishingiz mumkin, bunda hech qanday yangi funksiyalarni oʻrganishingiz shart emas.

    Siz faqat maxsus o'zgaruvchilarni o'rganishingiz kerak - kamida .N va .SD. dplyrdagi ekvivalent n() va .

  3. Qo'shiladi

    dplyr har bir ulanish turi uchun alohida funksiyalarni taqdim etadi, bunda data.table bir xil DT[i, j, by] sintaksisi (va sabab bilan) yordamida birlashishga ruxsat beradi. Shuningdek, u muqobil sifatida ekvivalent merge.data.table() funksiyasini taqdim etadi.

     setkey(DT1, x, y)
    
     # 1. normal join
     DT1[DT2]            ## data.table syntax
     left_join(DT2, DT1) ## dplyr syntax
    
     # 2. select columns while join    
     DT1[DT2, .(z, i.mul)]
     left_join(select(DT2, x, y, mul), select(DT1, x, y, z))
    
     # 3. aggregate while join
     DT1[DT2, .(sum(z) * i.mul), by = .EACHI]
     DF1 %>% group_by(x, y) %>% summarise(z = sum(z)) %>% 
         inner_join(DF2) %>% mutate(z = z*mul) %>% select(-mul)
    
     # 4. update while join
     DT1[DT2, z := cumsum(z) * i.mul, by = .EACHI]
     ??
    
     # 5. rolling join
     DT1[DT2, roll = -Inf]
     ??
    
     # 6. other arguments to control output
     DT1[DT2, mult = "first"]
     ??
    
  • Ba'zilar har bir qo'shilish uchun alohida funktsiyani ancha yaxshi (chap, o'ng, ichki, anti, yarim va h.

  • Biroq, dplyr qo'shilishlari buni amalga oshiradi. Boshqa hech narsa. Hech narsa kam emas.

  • data.tables qo'shilish paytida ustunlarni tanlashi mumkin (2) va dplyr da yuqorida ko'rsatilganidek, qo'shilishdan oldin ikkala data.framesda select() kerak bo'ladi. Aks holda, ularni keyinroq olib tashlash uchun keraksiz ustunlar bilan birlashishni amalga oshirasiz va bu samarasiz.

  • data.tables by = .EACHI funksiyasi (3) yordamida qo'shilish vaqtida jamlanishi va qo'shilish vaqtida yangilanishi (4) mumkin. Nega bir nechta ustunlarni qo'shish/yangilash uchun butun birlashma natijasini amalga oshirish kerak?

  • data.table birlashmalarni siljitishga qodir (5) - oldinga, LOCF, orqaga, NOCB, eng yaqin a>.

  • data.tableda birinchi, oxirgi yoki barcha mosliklarni tanlaydigan mult = argument ham mavjud (6).

  • data.table tasodifiy noto'g'ri ulanishlardan himoya qilish uchun allow.cartesian = TRUE argumentiga ega.

Yana bir bor, sintaksis DT[i, j, by] ga mos keladi, bu esa chiqishni keyingi nazorat qilish imkonini beruvchi qo'shimcha argumentlarga ega.

  1. do()...

    dplyr ning xulosasi bitta qiymatni qaytaradigan funktsiyalar uchun maxsus ishlab chiqilgan. Agar funktsiyangiz bir nechta/teng bo'lmagan qiymatlarni qaytarsa, siz do() ga murojaat qilishingiz kerak bo'ladi. Barcha funktsiyalaringizning qiymatini qaytarish haqida oldindan bilishingiz kerak.

     DT[, list(x[1], y[1]), by = z]                 ## data.table syntax
     DF %>% group_by(z) %>% summarise(x[1], y[1]) ## dplyr syntax
     DT[, list(x[1:2], y[1]), by = z]
     DF %>% group_by(z) %>% do(data.frame(.$x[1:2], .$y[1]))
    
     DT[, quantile(x, 0.25), by = z]
     DF %>% group_by(z) %>% summarise(quantile(x, 0.25))
     DT[, quantile(x, c(0.25, 0.75)), by = z]
     DF %>% group_by(z) %>% do(data.frame(quantile(.$x, c(0.25, 0.75))))
    
     DT[, as.list(summary(x)), by = z]
     DF %>% group_by(z) %>% do(data.frame(as.list(summary(.$x))))
    
  • .SD ning ekvivalenti .

  • Data.table da siz j ga deyarli hamma narsani tashlashingiz mumkin - esda tutish kerak bo'lgan yagona narsa - ro'yxatning har bir elementi ustunga aylantirilishi uchun ro'yxatni qaytarishdir.

  • Dplyrda buni qila olmaydi. Funktsiyangiz har doim bitta qiymatni qaytarishiga ishonchingiz komilligiga qarab do() ga murojaat qilishingiz kerak. Va bu juda sekin.

Yana bir bor, data.table sintaksisi DT[i, j, by] bilan mos keladi. Biz j ga iboralarni qo'yishda davom etishimiz mumkin.

bu SO savoliga va bu. Javobni dplyr sintaksisi yordamida to'g'ridan-to'g'ri ifodalash mumkinmi, deb o'ylayman ...

Xulosa qilib aytganda, men dplyr sintaksisi samarasiz, cheklangan yoki operatsiyalarni soddalashtira olmaydigan bir nechta holatlarni alohida ta'kidladim. Bu, ayniqsa, data.table sintaksisini o'qish/o'rganish qiyinroq (yuqorida qo'yilgan/bog'langan kabi) haqida biroz noroziliklarga duchor bo'lganligi bilan bog'liq. Dplyr-ni qamrab olgan ko'pgina postlar eng oddiy operatsiyalar haqida gapiradi. Va bu ajoyib. Ammo uning sintaksisi va xususiyatlarining cheklovlarini tushunish juda muhim va men hali bu haqda post ko'rmayapman.

data.table-ning o'ziga xos jihatlari ham bor (ba'zilarini tuzatishga harakat qilayotganimizni ta'kidladim). Biz bu yerda ta'kidlaganim uchun data.table-ning ulanishlarini ham yaxshilashga harakat qilmoqdamiz.

Ammo data.table bilan solishtirganda dplyrda etishmayotgan xususiyatlar sonini ham hisobga olish kerak.

4. Xususiyatlari

Ko'pgina xususiyatlarni bu yerda va shuningdek, ushbu postda ta'kidladim. Bunga qo'chimcha:

  • fread - tez fayllarni o'qish dasturi uzoq vaqtdan beri mavjud.

  • fwrite - endi parallellangan tezkor fayl yozuvchisi mavjud. Amalga oshirish bo'yicha batafsil tushuntirish uchun ushbu postga qarang. va keyingi ishlanmalarni kuzatib borish uchun #1664.

  • Avtomatik indekslash - R tayanch sintaksisini ichki sifatida optimallashtirish uchun yana bir qulay xususiyat.

  • Ad-hoc guruhlash: dplyr avtomatik ravishda natijalarni summarise() davomida oʻzgaruvchilarni guruhlash orqali tartiblaydi, bu har doim ham maʼqul boʻlmasligi mumkin.

  • Yuqorida aytib o'tilgan data.table birlashmalarining ko'plab afzalliklari (tezlik / xotira samaradorligi va sintaksisi uchun).

  • Teng bo'lmagan qo'shilishlar: Boshqa operatorlar yordamida ulanish imkonini beradi <=, <, >, >= va data.table birlashmalarining barcha boshqa afzalliklari.

  • Yaqinda data.tableda Bir-biriga o‘xshash diapazonlarni birlashtirish amalga oshirildi. Benchmarklar bilan umumiy ko'rinish uchun ushbu postni tekshiring.

  • setorder() maʼlumotlar jadvalidagi funksiya, bu maʼlumotlar jadvallarini mos yozuvlar boʻyicha tezda qayta tartiblash imkonini beradi.

  • dplyr xuddi shu sintaksisdan foydalangan holda ma'lumotlar bazalari interfeysini ta'minlaydi. data.table hozirda yo'q.

  • data.table qo'shimcha all argumentga ega (Yan Gorecki tomonidan yozilgan) - fsetdiff, fintersect, funion va fsetequal (SQLda bo'lgani kabi) to'plam operatsiyalarining tezroq ekvivalentlarini taqdim etadi.

  • data.table hech qanday niqoblash ogohlantirishlarisiz toza yuklanadi va har qanday R paketiga oʻtkazilganda [.data.frame muvofiqligi uchun bu yerda tasvirlangan mexanizmga ega. dplyr muammolarga olib kelishi mumkin bo'lgan filter, lag va [ asosiy funktsiyalarini o'zgartiradi; masalan. bu yerda va bu yerda.


Nihoyat:

  • Ma'lumotlar bazalarida - data.table shunga o'xshash interfeysni taqdim eta olmasligi uchun hech qanday sabab yo'q, ammo bu hozirda ustuvor emas. Agar foydalanuvchilar ushbu xususiyatni juda yoqtirsa, bu muammoga duch kelishi mumkin.. ishonchim komil.

  • Parallelizm bo'yicha - kimdir oldinga o'tib, buni qilmaguncha hamma narsa qiyin. Albatta, bu kuch talab qiladi (ip xavfsiz bo'lishi).

    • Progress is being made currently (in v1.9.7 devel) towards parallelising known time consuming parts for incremental performance gains using OpenMP.
person Community    schedule 31.12.2014
comment
... Shunday qilib, siz nima qilyapsiz (bir oz bilvosita) qatorlar kichik to'plami va bu dplyr da filter uchun yaratilgan. - person talat; 31.12.2014
comment
@docendodiscimus, uzr, lekin yana DT[, if(any(x>1)) y[1], by=z] qilishning idiomatik usuli qanday? Men endi gangib qoldim. Bu erda filtrdan foydalanishim kerakmi yoki kerak emasmi? - person Arun; 31.12.2014
comment

Loyihaga havola: SHU YERDA - Yuklab olish kerak!

Men sizga to'liq MVVM misolini taqdim etishga qaror qildim, shunda siz buni qanday qilib "to'g'ri" qilishni o'rganishingiz mumkin.

Eslatma: Men MVVM Light dan foydalanmoqdaman (bu RelayCommand uchun). Siz uni NuGet orqali o'rnatishingiz mumkin. Bunga arziydi, chunki u MVVM rivojlanishi uchun juda ko'p foydali sinflarni taqdim etadi. Unga yana bir muqobil - Prizma.

1. MVVM nima?

MVVM (Model - Ko'rish - ViewModel) - bu WPF bilan juda mos keladigan dasturlash naqshidir. Uning asosiy maqsadi dasturingiz mantig'i bo'lgan Ko'rishlarni - siz ko'rgan narsalaringizni ViewModelsdan ajratishdir.

Bu biroz ko'proq kodlashni talab qilishi mumkin, ammo foyda juda yaxshi - siz modulli va juda oson sinovdan o'tiladigan toza, tuzilgan kodga ega bo'lasiz (ya'ni, birlik testlari).

1.1 - Model

Model asosan dasturingizning tuzilishidir. Bu sizning sinflaringiz uchun ma'lumotlarga ega bo'lgan va keyinchalik ViewModels-da qo'llaniladigan magistralni ta'minlashi kerak.

Ushbu loyihaga kelsak, model yo'q, chunki u kerak emas (siz arizangiz bilan ishlayotganingizda, albatta kerak bo'ladi!)

1.2 - Ko'rish

Ko'rinish asosan siz ko'rgan narsadir. Ko'pincha bu oyna bo'lib, unda ko'rsatiladigan elementlar mavjud - lekin bu shunchaki bo'lishi shart emas! UserControl o'z-o'zidan Ko'rinish bo'lishi mumkin va unga o'zining ViewModel bog'langan bo'lishi mumkin - u joylashgan Oynadan boshqacha.

1.3 ViewModel

ViewModel asosan dasturingizning yadrosidir. U mantiqqa ega va ko'rinish o'zining boshqaruv elementlarida ulanishi va foydalanishi/ko'rsatishi mumkin bo'lgan xususiyatlarga ega. Buni arizangizning brain tasi deb hisoblang.

2. Kod

Ko'rish:

<Window x:Class="PasswordBoxMVVM.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:PasswordBoxMVVM"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:b="clr-namespace:System.Media;assembly=System"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:PasswordLengthToColorConverter x:Key="passwordLengthToColorConverter" />
</Window.Resources>
<Grid>
    <StackPanel VerticalAlignment="Center">
        <PasswordBox local:PasswordBoxMVVMAttachedProperties.EncryptedPassword="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                     IsEnabled="{Binding Path=IsPasswordFieldDisabled, Mode=TwoWay ,UpdateSourceTrigger=PropertyChanged}"
                     FontSize="20" Width="384" Height="34" PasswordChar="█" HorizontalAlignment="Center" FontFamily="Century Gothic" 
                     HorizontalContentAlignment="Left" VerticalContentAlignment="Center" TabIndex="2" Foreground="Red"
                     PasswordChanged="MyPasswordBox_PasswordChanged"
                     IsEnabledChanged="PasswordBox_IsEnabledChanged">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="PasswordChanged">
                    <i:InvokeCommandAction Command="{Binding Path=PasswordChangedCommand}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <PasswordBox.Style>
                <Style TargetType="{x:Type PasswordBox}">
                    <Setter Property="Background" Value="#FFCCCCCC" />
                    <Setter Property="BorderThickness" Value="0,2,0,2" />
                    <Setter Property="BorderBrush" Value="Red" />
                    <Setter Property="ClipToBounds" Value="true"/>
                    <Setter Property="OverridesDefaultStyle" Value="true"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="PasswordBox">
                                <Grid>
                                    <Border Background="{TemplateBinding Background}"
                                            BorderThickness="{TemplateBinding BorderThickness}"
                                            BorderBrush="{TemplateBinding Foreground}">
                                        <ScrollViewer x:Name="PART_ContentHost" Margin="0,-4,0,0"/>
                                    </Border>
                                    <TextBlock Name="TB" Text="Password" HorizontalAlignment="Left" Margin="140,0,0,0" VerticalAlignment="Center"  Opacity="0.3" Foreground="Gray">
                                    </TextBlock>
                                </Grid>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsFocused" Value="true">
                                        <Setter TargetName="TB" Property="Text" Value="Password:" />
                                        <Trigger.EnterActions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ThicknessAnimation Storyboard.TargetProperty="Padding" To="100,0,34,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <SineEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="2,0,0,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <SineEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3">
                                                        <DoubleAnimation.EasingFunction>
                                                            <SineEase EasingMode="EaseOut"/>
                                                        </DoubleAnimation.EasingFunction>
                                                    </DoubleAnimation>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </Trigger.EnterActions>
                                        <Trigger.ExitActions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ThicknessAnimation Storyboard.TargetProperty="Padding" To="230,0,0,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <BackEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="140,0,0,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <BackEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="0.3" Duration="0:0:0.3">
                                                        <DoubleAnimation.EasingFunction>
                                                            <BackEase EasingMode="EaseOut"/>
                                                        </DoubleAnimation.EasingFunction>
                                                    </DoubleAnimation>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </Trigger.ExitActions>
                                    </Trigger>

                                    <DataTrigger Binding="{Binding Path=IsPasswordFieldEmpty,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="false">
                                        <Setter TargetName="TB" Property="Text" Value="Password:" />
                                        <DataTrigger.EnterActions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ThicknessAnimation Storyboard.TargetProperty="Padding" To="100,0,34,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <SineEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="2,0,0,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <SineEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3">
                                                        <DoubleAnimation.EasingFunction>
                                                            <SineEase EasingMode="EaseOut"/>
                                                        </DoubleAnimation.EasingFunction>
                                                    </DoubleAnimation>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </DataTrigger.EnterActions>
                                        <DataTrigger.ExitActions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ThicknessAnimation Storyboard.TargetProperty="Padding" To="230,0,0,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <BackEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="140,0,0,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <BackEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="0.3" Duration="0:0:0.3">
                                                        <DoubleAnimation.EasingFunction>
                                                            <BackEase EasingMode="EaseOut"/>
                                                        </DoubleAnimation.EasingFunction>
                                                    </DoubleAnimation>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </DataTrigger.ExitActions>
                                    </DataTrigger>

                                    <MultiDataTrigger>
                                        <MultiDataTrigger.Conditions>
                                            <Condition Binding="{Binding Path=IsFocused, RelativeSource={RelativeSource Self}}" Value="false" />
                                            <Condition Binding="{Binding Path=IsPasswordFieldEmpty, UpdateSourceTrigger=PropertyChanged}" Value="true" />
                                        </MultiDataTrigger.Conditions>
                                        <Setter TargetName="TB" Property="Text" Value="Password" />
                                        <MultiDataTrigger.EnterActions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ThicknessAnimation Storyboard.TargetProperty="Padding" To="230,0,0,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <BackEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="140,0,0,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <BackEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="0.3" Duration="0:0:0.3">
                                                        <DoubleAnimation.EasingFunction>
                                                            <BackEase EasingMode="EaseOut"/>
                                                        </DoubleAnimation.EasingFunction>
                                                    </DoubleAnimation>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </MultiDataTrigger.EnterActions>
                                        <MultiDataTrigger.ExitActions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ThicknessAnimation Storyboard.TargetProperty="Padding" To="100,0,34,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <SineEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="2,0,0,0" Duration="0:0:0.3">
                                                        <ThicknessAnimation.EasingFunction>
                                                            <SineEase EasingMode="EaseOut"/>
                                                        </ThicknessAnimation.EasingFunction>
                                                    </ThicknessAnimation>
                                                    <DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3">
                                                        <DoubleAnimation.EasingFunction>
                                                            <SineEase EasingMode="EaseOut"/>
                                                        </DoubleAnimation.EasingFunction>
                                                    </DoubleAnimation>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </MultiDataTrigger.ExitActions>
                                    </MultiDataTrigger>

                                    <Trigger Property="IsEnabled" Value="false">
                                        <Setter TargetName="TB" Property="Text" Value="DISABLE"/>
                                        <Setter TargetName="TB" Property="Margin" Value="140,0,0,0"/>
                                        <Setter Property="Background" Value="#FFAAAAAA"/>
                                        <Setter Property="Foreground" Value="Gray"/>
                                        <Setter Property="BorderBrush" Value="#FF888888" />
                                        <Setter Property="BorderThickness" Value="0,3,0,3" />
                                    </Trigger>
                                    <Trigger Property="Tag" Value="ShowPW">
                                        <Setter Property="Visibility" Value="Hidden"/>
                                    </Trigger>
                                    <Trigger Property="Tag" Value="HidePW">
                                        <Setter Property="Visibility" Value="Visible"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                    </Style.Triggers>
                </Style>
            </PasswordBox.Style>
            <PasswordBox.Triggers>
                <EventTrigger RoutedEvent="PasswordBox.PasswordChanged">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="(PasswordBox.Foreground).(SolidColorBrush.Color)" 
                                            To="{Binding Path=Password.Length, UpdateSourceTrigger=PropertyChanged, 
                                            Converter={StaticResource passwordLengthToColorConverter}}" Duration="0:0:0.1">
                            </ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="local:PasswordBoxAttachedEvent.HasBeenDisabled">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="(PasswordBox.Foreground).(SolidColorBrush.Color)" 
                                            To="Gray" Duration="0:0:0.1">
                            </ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="local:PasswordBoxAttachedEvent.HasBeenEnabled">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="(PasswordBox.Foreground).(SolidColorBrush.Color)" 
                                            To="{Binding Path=Password.Length, UpdateSourceTrigger=PropertyChanged, 
                                            Converter={StaticResource passwordLengthToColorConverter}}" Duration="0:0:0.1">
                            </ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </PasswordBox.Triggers>
        </PasswordBox>
        <Button Width="200" Height="50" Margin="0,50,0,0" Command="{Binding Path=ClickCommand}">Click me</Button>
    </StackPanel>
</Grid>

This isn't much different from what you have provided, but it had been warped into MVVM - bindings, commands and converters were added. They are required to Bind (connect) our View and ViewModel.

Ko'rinishning kodi ortida:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        var vm = new PasswordViewModel();
        this.DataContext = vm;

        InitializeComponent();
    }

    private void MyPasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
    {
        PasswordBox pBox = sender as PasswordBox;
        PasswordBoxMVVMAttachedProperties.SetEncryptedPassword(pBox, pBox.SecurePassword);    
    }

    private void PasswordBox_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        PasswordBox pBox = sender as PasswordBox;

        if (pBox.IsEnabled == false)
        {
            RoutedEventArgs eventArgs = new RoutedEventArgs(PasswordBoxAttachedEvent.HasBeenDisabledEvent);
            pBox.RaiseEvent(eventArgs);
        }
        if (pBox.IsEnabled == true)
        {
            RoutedEventArgs eventArgs = new RoutedEventArgs(PasswordBoxAttachedEvent.HasBeenEnabledEvent);
            pBox.RaiseEvent(eventArgs);
        }
    }
}

Ko'rinish konstruktorida biz ViewModel-ni aniqlaymiz va uni View uchun DataContext sifatida o'rnatamiz.

Quyida voqealar va xususiyatlarni biriktirish imkonini beruvchi ba'zi hodisalarni ishlovchilar mavjud - lekin biz bu haqda keyinroq gaplashamiz.

Muhim: Agar siz MVVM haqida mustaqil oʻrganishni boshlaganingizda, odamlarning “Yaxshi MVVM-da Koʻrishda orqada kod boʻlmasligi kerak” degan gaplarini koʻrishingiz mumkin. Bu aslida to'liq bull**it :) Kodni ko'rishda hech qanday MVVM tamoyillarini buzmasa, orqaga qo'yish juda yaxshi - va ko'pincha ba'zi narsalarni kodlashni biroz osonlashtiradi.

ViewModel:

namespace PasswordBoxMVVM
{
    public class PasswordViewModel : ViewModelBase
    {
        private bool isPasswordFieldEmpty;
        public bool IsPasswordFieldEmpty
        {
            get { return isPasswordFieldEmpty; }
            set
            {
                isPasswordFieldEmpty = value;
                RaisePropertyChanged();
            }
        }

        private SecureString password;
        public SecureString Password
        {
            get { return password; }
            set
            {
                password = value;
                RaisePropertyChanged();
            }
        }

        private bool isPassWordFieldDisabled;
        public bool IsPasswordFieldDisabled
        {
            get { return isPassWordFieldDisabled; }
            set
            {
                isPassWordFieldDisabled = value;
                RaisePropertyChanged();
            }
        }

        public ICommand ClickCommand { get { return new RelayCommand(doAction, canDoAction); } }
        public ICommand PasswordChangedCommand { get { return new RelayCommand(updatePassword, canUpdatePassword); } }

        public PasswordViewModel()
        {
            // Init conditions, need them to not get null reference at the start.
            isPassWordFieldDisabled = true;
            IsPasswordFieldEmpty = true;
        }

        private void doAction()
        {
            IsPasswordFieldDisabled = !IsPasswordFieldDisabled;
        }

        private bool canDoAction()
        {
            // Replace this with any condition that you need.
            return true;
        }

        private void updatePassword()
        {
            if (Password != null)
            {
                if (Password.Length > 0)
                {
                    isPasswordFieldEmpty = false;
                }
                else
                {
                    isPasswordFieldEmpty = true;
                }
            }
            else
            {
                isPasswordFieldEmpty = true;
            }
        }

        private bool canUpdatePassword()
        {
            // Replace this with any condition that you need. 
            return true;
        }
    }
}

Bu erda juda ko'p narsalar sodir bo'lmoqda. Avvalo, bizda Parol, isPasswordFieldDisabled va boshqalar kabi ba'zi umumiy xususiyatlar mavjud. Bular bizning Ko'rinishimiz bilan bog'lanishi mumkin va bu bizga ViewModel'imizdan Ko'rinishni boshqarish imkonini beradi.

Shuningdek, bizda buyruqlar mavjud bo'lib, ular View-ning ViewModel bilan o'zaro ta'sir qilish usuli hisoblanadi. Ko'rinish ma'lum narsalarni ushbu buyruqlar bilan bog'laydi (masalan, hodisalar) va keyin biz ViewModel-da shunga asoslangan kodni bajaramiz.

Ushbu misolda tugmani bosish ViewModel-ga buyruqni ishga tushiradi, bu bizning PasswordBox isEnabled xususiyati bog'langan isPasswordBoxDisabled xususiyatini o'zgartiradi - amalda, View va ViewModel o'rtasida DIRECT o'zaro ta'sir qilmasdan PasswordBox-ni yoqish/o'chirish! Ajoyib, a?

Konverter

namespace PasswordBoxMVVM
{
    class PasswordLengthToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int length = (int)value;
            Color output = Colors.Red;

            if (length >= 0 && length < 5)
                output = Colors.Red;

            else if (length >= 5 && length < 6)
                output = Colors.Orange;

            else if (length >= 6 && length < 7)
                output = Colors.Yellow;

            else if (length >= 7 && length < 8)
                output = Colors.LightGreen;

            else if (length >= 8)
                output = Colors.Green;

            return output;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}

Konvertor tarjimonga o'xshaydi. Bu erda biz Parol uzunligini ranglarga aylantiramiz - keyin ularni animatsiyada ishlatishimiz uchun. Bu MVVM modulli ekanligini aytganimda nimani nazarda tutganimning ajoyib namunasidir - siz boshqa konvertatsiya qilishni xohlaysizmi? Shunchaki yangi konvertorga bog'lang va ish tugadi, Ko'rinishni qayta yozishingiz shart emas!

Parol biriktirilgan xususiyat - bog'langan loyihani ko'ring

Bu bizning PasswordBox parolini ViewModelimizga bog'lashimiz uchungina bu yerda. Dastlab, PasswordBox buni qo'llab-quvvatlamaydi. Biriktirilgan xususiyatlarni kiriting! Bu bizning PasswordBox imkoniyatlarini "kengaytirish" imkonini beradi, unga yangi xususiyatni (shuning uchun nomi) biriktirish orqali - biz ViewModel bilan bog'lashimiz mumkin.

Xuddi shu narsa biriktirilgan voqealar uchun ham amal qiladi - kodda qolgan hamma narsani topishingiz mumkin, chunki belgilar kvotasi meni ko'proq joylashtirishni cheklaydi.

- person Arun; 31.12.2014
comment
Siz qatorlarni o'rnatayotganingiz uchun filtrdan foydalanishingiz kerak. (Sizning misolingizda siz z guruhining hech birini olib tashlamaysiz, chunki ularning ikkalasida ham any(x > 1) == TRUE mavjud. Demak, siz shunday qilishni xohlaysiz: DF %>% group_by(z) %>% filter(any(x > 1)) %>% summarise(y = y[1]). - person talat; 31.12.2014
comment
Sharhlar kengaytirilgan muhokama uchun emas; bu suhbat chatga o'tdi. - person Taryn; 31.12.2014
comment
@bluefeet: Menimcha, siz ushbu munozarani suhbatga o'tkazish orqali qolganlarimizga katta xizmat qilganingiz yo'q. Men Arunni ishlab chiquvchilardan biri deb taassurot qoldirdim va bu foydali tushunchalarga olib kelishi mumkin edi. - person IRTFM; 06.01.2015
comment
@BondedDust Muammo shundaki, ushbu postda 30 dan ortiq sharhlar mavjud bo'lib, ularda foydali bo'lgan narsalarni topish juda qiyin. Barcha sharhlar suhbatga ko'chirildi, keyin kerak bo'lganda ular javobga kiritilishi mumkin edi. Izohlarda kengaytirilgan muhokamalar bo'lmasligi kerak, chat aynan shu uchun. - person Taryn; 06.01.2015
comment
Men sizning havolangiz orqali suhbatga borganimda, siz filtrdan foydalanishingiz kerak. Menga SO-chat mexanizmi haqida biror narsa etishmayaptimi? - person IRTFM; 06.01.2015
comment
@BondedDust Filtrlash kerak... sharhidan keyin bu yerda yoki chatda qo‘shimcha izohlar yo‘q edi. Bu yerda ham, chatda ham hech kim muhokamani davom ettirmaganga o‘xshaydi. - person Taryn; 06.01.2015
comment
O'ylaymanki, siz topshiriqni mos yozuvlar bo'yicha ishlatayotgan har bir joyda (:=), dplyr ekvivalenti faqat DF %>% mutate... o'rniga DF <- DF %>% mutate... dagi kabi <- dan foydalanishi kerak. - person David Arenburg; 07.01.2015
comment
Sintaksis haqida. Menimcha, dplyr plyr sintaksisini ishlatgan foydalanuvchilar uchun osonroq bo'lishi mumkin, ammo data.table SQL kabi tillar sintaksisini va uning orqasida jadval ma'lumotlarini o'zgartirish bilan bog'liq bo'lgan relyatsion algebrani so'ragan foydalanuvchilar uchun osonroq bo'lishi mumkin. @Arun shuni ta'kidlash kerakki, o'rnatish operatorlari data.table funksiyasini o'rash orqali juda oson bajarilishi mumkin va, albatta, sezilarli tezlikni keltirib chiqaradi. - person jangorecki; 14.01.2015
comment
funktsiyaga dplyr qo'shing va darhol eksponent jihatdan murakkab kodni ko'ring. ularni ham taqqoslashingizga qo'shishingiz kerak - person MySchizoBuddy; 10.06.2016
comment
@MySchizoBuddy, ehtimol siz nima haqida gaplashayotganingizni ko'rsatish uchun asosiy narsa? Siz tegishli SE versiyasimi? - person Arun; 15.06.2016
comment
@Arun yes dplyr funksiyasidan foydalanilganda funktsiya ichida foydalanilganda siz SE versiyalarini lazyeval::interp() bilan birga ishlatishingiz kerak data.table funksiyadan foydalanishda shunga o'xshash muammolar bormi - person MySchizoBuddy; 16.06.2016
comment
@MySchizoBuddy, yaxshi fikr. data.table ning .SD va .SDcols bilan birga interp() AFAIU ga qaraganda ancha sodda, hech bo'lmaganda ko'pgina stsenariylar uchun. Bu get() va mget() (kamdan-kam hollarda) foydalanish bilan birga barcha stsenariylarning ~ 99% da etarli. [data.table i-argumentda yana bir narsani amalga oshirishi kerak - yaxshiroq qamrovli qoidalar, lekin bu juda kam uchraydigan stsenariy.] Agar interp() ni tushuna olsam, buni postda tahrirlash yo‘lini o‘ylab ko‘raman. rahmat. - person Arun; 16.06.2016
comment
@Arun Men data.table ma'lumotlar bazasini qo'llab-quvvatlashni juda xohlayman! Redshift backendida data.table sintaksisini tasavvur qiling. Ehtimol, iloji bo'lsa, qimmat takrorlanadigan so'rovlarni oldini olish uchun mahalliy keshlash qatlami bilan. Voy-buy. - person andrew; 08.08.2018
comment
Men bu postni ko'p marta o'qib chiqdim va bu menga data.tableni tushunish va undan yaxshiroq foydalanishga yordam berdi. Men ko'p hollarda dplyr yoki pandas yoki PL/pgSQL o'rniga data.table ni afzal ko'raman. Biroq, men buni qanday ifodalash haqida o'ylay olmadim. Sintaksis emas oson, aniq yoki batafsil. Darhaqiqat, men data.table-dan ko'p foydalanganimdan keyin ham, men ko'pincha o'z kodimni tushunishga qiynalib, bir hafta oldin yozganman. Bu faqat yoziladigan tilning hayotiy misolidir. en.wikipedia.org/wiki/Write-only_language Shunday ekan, bir kun kelib umid qilaylik. data.table da dplyr dan foydalanishimiz mumkin bo'ladi. - person Ufos; 18.12.2018
comment
c) va b) 1. Asosiy yig'ish/yangilash operatsiyalari. Men dplyr va dt dan ekvivalent natijalarga erishmayapman. - person its.me.adam; 05.03.2020
comment
Aslida dplyr kodining ko'pi endi qo'llanilmaydi (yangilanishlar tufaylimi?)... Bu javob yangilanishdan foydalanishi mumkin, chunki u ajoyib manba. - person its.me.adam; 05.03.2020
comment
@its.me.adam muammo shundaki, bu kod vaqt o'tishi bilan bir necha marta o'zgargan, shuning uchun uni yangilash aslida befoyda, chunki bir muncha vaqt o'tgach, siz yana yangilashingiz kerak bo'ladi. Qo'lda yozuvlarni qidirish (joriy API uchun) unchalik qiyin emas. - person jangorecki; 20.10.2020
comment
@Ufos endi data.table ga tarjima qilingan dplyr sintaksisidan foydalanishingiz mumkin (bu eng tezkor kod bo'lmasligi mumkin, lekin bu boshlang'ich); cran.r-project.org/web/packages/dtplyr/index. html - person llrs; 10.06.2021

Mana, Arunning javobining keng ko'rinishidan so'ng, dplyr nuqtai nazaridan keng qamrovli javob berishga urinishim (lekin turli xil ustuvorliklar asosida biroz qayta tashkil etilgan).

Sintaksis

Sintaksisning sub'ektivligi bor, lekin men ma'lumotlar jadvalining ixchamligi uni o'rganishni qiyinlashtiradi va o'qishni qiyinlashtiradi degan gapimga sodiqman. Bu qisman, chunki dplyr ancha oson muammoni hal qiladi!

Dplyr siz uchun qiladigan juda muhim narsa shundaki, u sizning imkoniyatlaringizni cheklaydi. Men bitta jadval muammolarini faqat beshta asosiy fe'llarni filtrlash, tanlash, o'zgartirish, tartibga solish va umumlashtirish, shuningdek "guruh bo'yicha" qo'shimchasi bilan hal qilish mumkinligini da'vo qilaman. Ushbu cheklov ma'lumotlarni manipulyatsiya qilishni o'rganayotganda katta yordam beradi, chunki u muammo haqida fikr yuritishga yordam beradi. Dplyrda bu fe'llarning har biri bitta funktsiyaga moslashtirilgan. Har bir funktsiya bitta vazifani bajaradi va uni alohida tushunish oson.

Ushbu oddiy operatsiyalarni %>% bilan birlashtirib, murakkablikni yaratasiz. Mana Arun bog'langan postlaridan biriga misol:

diamonds %>%
  filter(cut != "Fair") %>%
  group_by(cut) %>%
  summarize(
    AvgPrice = mean(price),
    MedianPrice = as.numeric(median(price)),
    Count = n()
  ) %>%
  arrange(desc(Count))

Agar siz ilgari hech qachon dplyr (yoki hatto R!) ni ko'rmagan bo'lsangiz ham, nima sodir bo'layotganini tushunishingiz mumkin, chunki funktsiyalarning barchasi ingliz fe'llaridir. Ingliz tilidagi fe'llarning kamchiligi shundaki, ular [ dan ko'ra ko'proq yozishni talab qiladi, lekin men buni yaxshi avtomatik to'ldirish orqali engillashtirish mumkin deb o'ylayman.

Mana ekvivalent data.table kodi:

diamondsDT <- data.table(diamonds)
diamondsDT[
  cut != "Fair", 
  .(AvgPrice = mean(price),
    MedianPrice = as.numeric(median(price)),
    Count = .N
  ), 
  by = cut
][ 
  order(-Count) 
]

Agar data.table bilan tanish bo'lmasangiz, ushbu kodga amal qilish qiyinroq. (Ko'zimga yaxshi ko'rinadigan tarzda takrorlangan [ ni qanday qilib chekinishni ham tushunolmadim). Shaxsan men 6 oy oldin yozgan kodni ko'rib chiqsam, bu xuddi notanish odam tomonidan yozilgan kodni ko'rishga o'xshaydi, shuning uchun men to'g'ridan-to'g'ri, agar batafsil bo'lsa, kodni afzal ko'raman.

O'qishni biroz pasaytiradigan yana ikkita kichik omil:

  • Deyarli har bir ma'lumotlar jadvali operatsiyasi [ dan foydalanganligi sababli, nima sodir bo'layotganini aniqlash uchun sizga qo'shimcha kontekst kerak. Misol uchun, x[y] ikkita ma'lumotlar jadvalini birlashtirdimi yoki ma'lumotlar ramkasidan ustunlarni ajratib oladimi? Bu faqat kichik masala, chunki yaxshi yozilgan kodda o'zgaruvchilar nomlari nima bo'layotganini ko'rsatishi kerak.

  • Menga group_by() dplyr-da alohida operatsiya ekanligi yoqadi. Bu hisoblashni tubdan o'zgartiradi, shuning uchun men kodni ko'zdan kechirishda aniq bo'lishi kerak deb o'ylayman va [.data.table ga by argumentidan ko'ra group_by() ni aniqlash osonroq.

Menga quvur faqat bitta paket bilan cheklanmagani ham yoqadi. Maʼlumotlaringizni tartibga solishni tidyr bilan boshlashingiz va shu bilan tugatishingiz mumkin. ggvis da syujet. Va siz men yozadigan paketlar bilan cheklanmaysiz - har kim ma'lumotlarni manipulyatsiya qilish quvurining uzluksiz qismini tashkil etuvchi funktsiyani yozishi mumkin. Aslida, men %>% bilan qayta yozilgan oldingi data.table kodini afzal ko'raman:

diamonds %>% 
  data.table() %>% 
  .[cut != "Fair", 
    .(AvgPrice = mean(price),
      MedianPrice = as.numeric(median(price)),
      Count = .N
    ), 
    by = cut
  ] %>% 
  .[order(-Count)]

Va %>% bilan quvurlarni ulash g'oyasi faqat ma'lumotlar ramkalari bilan chegaralanib qolmaydi va boshqa kontekstlarga osongina umumlashtiriladi: interaktiv veb-grafika, veb qirqish, ma'nolari, ish vaqti shartnomalari, ...)

Xotira va ishlash

Men bularni birlashtirdim, chunki men uchun ular unchalik muhim emas. Aksariyat R foydalanuvchilari 1 milliondan kam maʼlumotlar qatori bilan ishlaydi va dplyr qayta ishlash vaqtini bilmaydigan maʼlumotlar hajmi uchun yetarlicha tezdir. Biz o'rta ma'lumotlarda ekspressivlik uchun dplyrni optimallashtiramiz; Kattaroq maʼlumotlarda tezkorlik uchun data.table dan foydalaning.

Dplyr-ning moslashuvchanligi, shuningdek, bir xil sintaksisdan foydalanib, ishlash xususiyatlarini osongina sozlashingiz mumkinligini anglatadi. Agar ma'lumotlar ramkasi backend bilan dplyr unumdorligi siz uchun etarli bo'lmasa, data.table backendidan foydalanishingiz mumkin (biroz cheklangan funksiyalar to'plamiga qaramay). Agar siz ishlayotgan ma'lumotlar xotiraga to'g'ri kelmasa, siz ma'lumotlar bazasidan foydalanishingiz mumkin.

Aytgancha, dplyr ishlashi uzoq muddatda yaxshilanadi. Biz, albatta, data.tablening ba'zi ajoyib g'oyalarini amalga oshiramiz, masalan, radix tartiblash va birlashmalar va filtrlar uchun bir xil indeksdan foydalanish. Biz bir nechta yadrolardan foydalanishimiz uchun parallellashtirish ustida ham ishlayapmiz.

Xususiyatlari

2015-yilda ishlashni rejalashtirgan bir nechta narsalar:

  • fread() ga o'xshash fayllarni diskdan va xotiraga olishni osonlashtirish uchun readr paketi.

  • Ko'proq moslashuvchan birikmalar, jumladan, teng bo'lmagan qo'shilishlarni qo'llab-quvvatlash.

  • Bootstrap namunalari, rollups va boshqalar kabi moslashuvchan guruhlash

Shuningdek, men R ning ma'lumotlar bazasi ulagichlarini, veb-apis va uni html sahifalarini qirib tashlash.

person hadley    schedule 08.01.2015
comment
Shunchaki yon eslatma, men sizning ko'pgina argumentlaringizga qo'shilaman (garchi men o'zim data.table sintaksisini afzal ko'raman), lekin [ uslubini yoqtirmasangiz, data.table operatsiyalarini o'tkazish uchun %>% dan osongina foydalanishingiz mumkin. %>% dplyr ga xos emas, aksincha alohida paketdan (siz hammuallifisiz), shuning uchun Sintaksis<da nima demoqchi ekanligingizni tushunmayapman. /b> paragraf. - person David Arenburg; 08.01.2015
comment
@DavidArenburg yaxshi nuqta. Asosiy fikrlarim nima ekanligini aniqroq qilish va data.table bilan %>% dan foydalanishingiz mumkinligini ta'kidlash uchun sintaksisni qayta yozdim. - person hadley; 08.01.2015
comment
Rahmat Xadli, bu foydali istiqbol. Qayta chekinish Men odatda DT[\n\texpression\n][\texpression\n] (gist)ni bajaraman, bu aslida juda yaxshi ishlaydi yaxshi. Men Arunning javobini javob sifatida saqlayman, chunki u sintaksisning mavjudligi bilan bog'liq bo'lmagan maxsus savollarimga to'g'ridan-to'g'ri javob beradi, lekin menimcha, bu dplyr o'rtasidagi farqlar/umumiyliklar haqida umumiy tasavvurga ega bo'lishga harakat qilayotgan odamlar uchun yaxshi javob. va data.table. - person BrodieG; 08.01.2015
comment
Kichik bir nuqta: birlashmalarni data.frame ustunlar to'plamidan ajratish uchun siz X[J(Y)] yoki X[.(Y)] ni bajarishingiz mumkin. - person Arun; 08.01.2015
comment
@BrodieG bu juda yaxshi, lekin men uni hali ham yoqtirmayman. - person hadley; 08.01.2015
comment
Haqqoniy. Men baxtli data.table foydalanuvchi (va vaqti-vaqti bilan dplyr foydalanuvchi) bo'lsam-da, vaqti-vaqti bilan men data.table [ ichida juda ko'p narsa qilishga urinishini his qilaman. - person BrodieG; 08.01.2015
comment
@BrodieG [ operatorida munosabatlar algebrasi uchun zarur bo'lgan hamma narsani qo'yib, SQL so'rovlariga< to'g'ridan-to'g'ri o'xshash (va chuqur kengaytma) bo'lishi mumkin bo'lgan data.table so'rovlarini hosil qiladi. /b>. Ayni paytda men [ argning hech qanday ortiqchasini ko'rmayapman (drop dan tashqari) va ha, ularning ko'pi allaqachon mavjud :) - person jangorecki; 08.01.2015
comment
@JanGorecki, menda data.table ning qancha argumentlari borligi bilan bog'liq hech qanday muammo yo'q (men buni yomon ifodaladim), lekin ba'zida men i ni qo'shilish va indekslash uchun ishlatmaslik kerak deb o'ylayman, garchi ixcham sintaksis yaxshi bo'lsa ham ( merge dan farqli o'laroq), shuning uchun men bu haqda asosan aralash his-tuyg'ularga egaman. - person BrodieG; 08.01.2015
comment
fread() bo'lsa, nima uchun tezkor o'qish ustida ishlash kerak? Vaqtni fread() ni takomillashtirish yoki boshqa (kam rivojlangan) narsalar ustida ishlashga sarflash yaxshiroq emasmi? - person EDi; 28.01.2015
comment
@EDi, chunki fastread va fread turli maqsadlarga ega. fastread shuningdek C++ api-ni taqdim etadi, shuning uchun siz yangi fayl formatlarida o'qish uchun bir xil asosiy koddan foydalanishingiz mumkin - person hadley; 28.01.2015
comment
data.table API'si [] belgisini katta suiiste'mol qilish asosida yaratilgan. Bu uning eng katta kuchi va eng katta zaifligi. - person Paul; 28.01.2016
comment
@DavidArenburg quvur operatoridan foydalangan holda yuqoridagi misolda siz 4 ta nuqta borligini payqadingiz(.) Ulardan ikkitasi maʼlumotlar obyektining oʻzi uchun, qolgan ikkitasi esa yoʻq. Bu men uchun shunchaki chalkash. - person MySchizoBuddy; 20.06.2016
comment
Katta hajmdagi maʼlumotlarda data.tabledan foydalanishga ruxsat berganingiz uchun tashakkur! Faqat bu javobga arziydi. - person piccolbo; 01.05.2018
comment
Men siz ko‘rsatayotgan data.table parchasini dplyr : dan afzal ko‘raman va 18 oy oldin kichik vazifa uchun data.table dan faqat bir marta foydalandim. Juda o'qilishi mumkin va qisqa. python-yerda mantiqiy parallellik bo'lishini xohlayman. python-dagi datatable paketi asta-sekin yaxshilanmoqda, lekin r data.table ga tegishni boshlamaydi. - person WestCoastProjects; 30.03.2020

Savol sarlavhasiga bevosita javob sifatida...

dplyr albatta data.table qila olmaydigan ishlarni qiladi.

Sizning fikringiz №3

dplyr potentsial JB o'zaro ta'sirlarini abstrakt qiladi (yoki bo'ladi).

bu sizning savolingizga to'g'ridan-to'g'ri javob, lekin etarlicha yuqori darajaga ko'tarilmagan. dplyr haqiqatan ham bir nechta ma'lumotlarni saqlash mexanizmlari uchun kengaytiriladigan old qismdir, chunki data.table bittasining kengaytmasi.

dplyr ga orqa tomonli agnostik interfeys sifatida qarang, barcha maqsadlar bir xil grammatikadan foydalanadi, bu erda siz maqsadlar va ishlov beruvchilarni xohlaganingizcha kengaytirishingiz mumkin. data.table, dplyr nuqtai nazaridan, bu maqsadlardan biri.

Siz hech qachon (umid qilamanki) data.table diskdagi yoki tarmoqqa ulangan ma'lumotlar do'konlari bilan ishlaydigan SQL bayonotlarini yaratish uchun so'rovlaringizni tarjima qilishga urinadigan kunni ko'rmaysiz.

dplyr data.table qila olmaydigan ishlarni ham qila oladi.

Xotirada ishlash dizayniga asoslanib, data.table dplyr ga qaraganda so'rovlarni parallel qayta ishlashga kengayishi ancha qiyin bo'lishi mumkin.


Tanadagi savollarga javoban...

Foydalanish

U yoki bu paket bilan kodlash ancha oson bo‘lgan analitik vazifalar bormi? yaxshi narsa).

Bu punt kabi ko'rinishi mumkin, ammo haqiqiy javob yo'q. Asboblar bilan tanish odamlar o'zlariga eng tanish yoki ish uchun mos bo'lganidan foydalanadilar. Aytgancha, ba'zida siz ma'lum bir o'qish qobiliyatini, ba'zan esa ishlash darajasini ko'rsatishni xohlaysiz va ikkalasining ham etarlicha yuqori darajasiga muhtoj bo'lganingizda, aniqroq mavhumlikni yaratishingiz kerak bo'lgan narsa bilan birga borish uchun boshqa vosita kerak bo'lishi mumkin. .

Umumiylik

Bir paketda boshqasiga nisbatan sezilarli darajada (ya'ni 2x dan ortiq) samaraliroq bajariladigan analitik vazifalar bormi?

Yana, yo'q. data.table hamma narsada samarali bo'lishda ustundirbu dplyr ba'zi jihatlarda asosiy ma'lumotlar ombori va ro'yxatdan o'tgan ishlovchilar bilan cheklanish yukini oladi.

Bu shuni anglatadiki, data.table bilan ishlash muammosiga duch kelganingizda, bu sizning so'rovlar funksiyangizda ekanligiga ishonchingiz komil bo'lishi mumkin va agar u data.table bilan bog'liq bo'lsa, demak, siz o'zingizga hisobot berish quvonchini qo'lga kiritgansiz. . Bu dplyr orqa tomon sifatida data.table dan foydalanganda ham to'g'ri bo'ladi; dplyr dan ba'zi qo'shimcha xarajatlarni ko'rishingiz mumkin, ammo ehtimol bu sizning so'rovingiz.

dplyr da orqa uchlari bilan ishlash muammosi bo'lsa, siz gibrid baholash funksiyasini ro'yxatdan o'tkazish yoki (ma'lumotlar bazalari uchun) bajarilishdan oldin yaratilgan so'rovni boshqarish orqali ularni hal qilishingiz mumkin.

Shuningdek, qachon plyr data.tabledan yaxshiroq bo'lsa, qabul qilingan javobni ko'ring. ?

person Thell    schedule 16.11.2014
comment
dplyr ma'lumotlar jadvalini tbl_dt bilan o'rab bo'lmaydimi? Nima uchun ikkala dunyoning eng yaxshisini qo'lga kiritmaysiz? - person aaa90210; 09.12.2014
comment
@aaa90210, ushbu postga> - person BrodieG; 17.12.2014
comment
Siz teskari bayonotni eslatishni unutasiz data.table albatta dplyr qila olmaydigan narsalarni qiladibu ham to'g'ri. - person jangorecki; 05.01.2015
comment
@JanGorecki Buning sababi, men data.table ning dplyr to'g'ridan-to'g'ri yoki ishlov beruvchilar orqali qodir bo'lmagan qobiliyatini bilmayman. Savolning OPning sifat (yomon) qismiga javoban farqlar sifatida muhokama qilingan xususiyatlar (tezlik, xotira va sintaksis nuqtai nazaridan muhokama qilinganidek) mavjud. Qatlamni umumlashtirish va mavhumlashtirish mumkin bo'lmagan imkoniyatlarni ko'rganingizni eslamang. - person Thell; 05.01.2015
comment
Arun javobi buni yaxshi tushuntiradi. Eng muhimi (ishlash nuqtai nazaridan) fread, mos yozuvlar bo'yicha yangilash, siljish birlashmalari, bir-biriga mos keladigan birikmalar bo'ladi. Menimcha, bu xususiyatlar bilan raqobatlasha oladigan hech qanday paket (nafaqat dplyr) yo'q. Yaxshi misol ushbu taqdimotdan olingan oxirgi slayd bo'lishi mumkin. - person jangorecki; 05.01.2015
comment
Umuman olganda, data.table nima uchun men hali ham R dan foydalanaman. Aks holda pandalardan foydalanardim. Bu pandalardan ham yaxshiroq/tezroq. - person marbel; 02.12.2016
comment
Menga data.table oddiyligi va SQL sintaksisi tuzilishiga o'xshashligi tufayli yoqadi. Mening ishim statistik modellashtirish uchun har kuni maxsus ma'lumotlarni tahlil qilish va grafikalarni bajarishni o'z ichiga oladi va menga murakkab narsalarni qilish uchun juda oddiy vosita kerak. Endi men kundalik ishimda asboblar to'plamini faqat ma'lumotlar uchun data.table va grafik uchun panjaraga qisqartirishim mumkin. Misol keltiring, men hatto shunday operatsiyalarni ham qila olaman: $DT[group==1,y_hat:=predict(fit1,data=.SD),]$, bu juda chiroyli va men buni SQL-dan katta afzallik deb bilaman. klassik R muhiti. - person xappppp; 31.12.2016

Xedli va Arunning javoblarini o'qib, dplyr sintaksisini afzal ko'rganlar ba'zi hollarda data.table ga o'tishlari yoki uzoq vaqt davomida murosaga kelishlari mumkin degan taassurot paydo bo'ladi.

Ammo ba'zilar allaqachon aytib o'tganidek, dplyr data.table dan backend sifatida foydalanishi mumkin. Bu yaqinda 1.0.0 versiyasiga ega bo'lgan dtplyr paketi yordamida amalga oshiriladi chiqarish. dtplyr ni o'rganish deyarli nol qo'shimcha kuch sarflaydi.

dtplyr dan foydalanilganda dangasa ma'lumotlar jadvalini e'lon qilish uchun lazy_dt() funksiyasidan foydalaniladi, shundan so'ng undagi operatsiyalarni belgilash uchun standart dplyr sintaksisi qo'llaniladi. Bu quyidagi kabi ko'rinadi:

new_table <- mtcars2 %>% 
  lazy_dt() %>%
  filter(wt < 5) %>% 
  mutate(l100k = 235.21 / mpg) %>% # liters / 100 km
  group_by(cyl) %>% 
  summarise(l100k = mean(l100k))

  new_table

#> Source: local data table [?? x 2]
#> Call:   `_DT1`[wt < 5][, `:=`(l100k = 235.21/mpg)][, .(l100k = mean(l100k)), 
#>     keyby = .(cyl)]
#> 
#>     cyl l100k
#>   <dbl> <dbl>
#> 1     4  9.05
#> 2     6 12.0 
#> 3     8 14.9 
#> 
#> # Use as.data.table()/as.data.frame()/as_tibble() to access results

new_table ob'ekti as.data.table()/as.data.frame()/as_tibble() chaqirilmaguncha baholanmaydi, shu nuqtada asosiy data.table operatsiyasi bajariladi.

Men dekabrda data.table yil muallifi Mett Doul tomonidan amalga oshirilgan sinov tahlilini qayta yaratdim 2018 yil, bu ko'p sonli guruhlardagi operatsiyalarni qamrab oladi. Men dtplyr haqiqatan ham dplyr sintaksisini afzal ko'rganlarga data.table tomonidan taqdim etilgan tezlikdan bahramand bo'lgan holda undan foydalanishni davom ettirish imkonini berishini aniqladim.

person Iyar Lin    schedule 14.06.2020
comment
Sizda dplyr-da API mavjud bo'lmagan ko'p funksiyalar bo'lmasligi mumkin, masalan, mos yozuvlar bo'yicha pastki tayinlash, siljishlar, bir-biriga o'xshash qo'shilishlar, teng bo'lmagan birlashmalar, qo'shilishda yangilanishlar va ehtimol boshqalar. - person jangorecki; 24.06.2020
comment
Tan olishim kerakki, bu xususiyatlarning hech biri qo'ng'iroq qilmaydi. Data.table da aniq misollar keltira olasizmi? - person Iyar Lin; 25.06.2020
comment
?data.table ta misol, hammasi bir-biriga o'xshashlardan tashqari qo'shiladi. bormi - person jangorecki; 26.06.2020
comment
Birlashma, dumalash, bir-birining ustiga qo'yish bo'yicha yangilanishlar quvurning bir nechta qismlari bilan to'g'ridan-to'g'ri tuzilishi mumkin. - person Arthur Yip; 16.10.2020
comment
Teng bo'lmagan qo'shilishlar uchun fuzzyjoin-ga qarang (data.tablening teng bo'lmagan qo'shilishlariga qaraganda ko'proq xususiyat va funksionallikka ega ko'rinadi). - person Arthur Yip; 16.10.2020