2015-06-02 17 views
6

In definitiva, io sto cercando di realizzare qualcosa di simile a quanto segue, ma sfruttando dplyr invece di plyr:Qual è l'equivalente dplyr di plyr :: ldply (tapply) in R?

library(dplyr) 
probs = seq(0, 1, 0.1) 

plyr::ldply(tapply(mtcars$mpg, 
        mtcars$cyl, 
        function(x) { quantile(x, probs = probs) })) 

# .id 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% 
# 1 4 21.4 21.50 22.80 22.80 24.40 26.0 27.30 30.40 30.40 32.40 33.9 
# 2 6 17.8 17.98 18.32 18.98 19.40 19.7 20.48 21.00 21.00 21.16 21.4 
# 3 8 10.4 11.27 13.90 14.66 15.04 15.2 15.44 15.86 16.76 18.28 19.2 

Il miglior dplyr equivalente posso venire in mente è qualcosa di simile:

library(tidyr) 
probs = seq(0, 1, 0.1) 

mtcars %>% 
    group_by(cyl) %>% 
    do(data.frame(prob = probs, stat = quantile(.$mpg, probs = probs))) %>% 
    spread(prob, stat) 

# cyl 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 
# 1 4 21.4 21.50 22.80 22.80 24.40 26.0 27.30 30.40 30.40 32.40 33.9 
# 2 6 17.8 17.98 18.32 18.98 19.40 19.7 20.48 21.00 21.00 21.16 21.4 
# 3 8 10.4 11.27 13.90 14.66 15.04 15.2 15.44 15.86 16.76 18.28 19.2 

Si noti che è necessario utilizzare anche lo tidyr::spread. Inoltre, si noti che ho perso la formattazione % per le intestazioni di colonna a vantaggio della sostituzione di .id con cyl nella prima colonna.

Domande:

  1. c'è una migliore dplyr approccio alla realizzazione di questo tapply %>% ldply catena?
  2. C'è un modo per ottenere il meglio da entrambi i mondi senza saltare attraverso troppi cerchi? Vale a dire, ottenere la formattazione e il corretto nome colonna cyl per la prima colonna?

risposta

7

Utilizzando dplyr

library(dplyr) 
mtcars %>% 
    group_by(cyl) %>% 
    do(data.frame(as.list(quantile(.$mpg,probs=probs)), check.names=FALSE)) 
# cyl 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% 
#1 4 21.4 21.50 22.80 22.80 24.40 26.0 27.30 30.40 30.40 32.40 33.9 
#2 6 17.8 17.98 18.32 18.98 19.40 19.7 20.48 21.00 21.00 21.16 21.4 
#3 8 10.4 11.27 13.90 14.66 15.04 15.2 15.44 15.86 16.76 18.28 19.2 

O un'opzione usando data.table

library(data.table) 
as.data.table(mtcars)[, as.list(quantile(mpg, probs=probs)) , cyl] 
# cyl 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% 
#1: 6 17.8 17.98 18.32 18.98 19.40 19.7 20.48 21.00 21.00 21.16 21.4 
#2: 4 21.4 21.50 22.80 22.80 24.40 26.0 27.30 30.40 30.40 32.40 33.9 
#3: 8 10.4 11.27 13.90 14.66 15.04 15.2 15.44 15.86 16.76 18.28 19.2 
+0

cura di spiegare 'check.names = FALSE'? – JasonAizkalns

+0

@JasonAlzkains È un argomento in 'data.frame' dove l'opzione predefinita è' check.names = TRUE'. Quindi, se i nomi delle colonne iniziano con valori non numerici, verrà aggiunto "X" ad esso. Il codice rilevante è 'if (check.names) vnames <- make.names (vnames, unique = TRUE)' – akrun

5

@ versione del akrun è buono, ma vorrei usare data_frame_ all'interno dell'istruzione do.

mtcars %>% 
    group_by(cyl) %>% 
    do(data_frame_(quantile(.$mpg, probs = probs))) 
## Source: local data frame [3 x 12] 
## Groups: cyl 
## 
## cyl 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% 
## 1 4 21.4 21.50 22.80 22.80 24.40 26.0 27.30 30.40 30.40 32.40 33.9 
## 2 6 17.8 17.98 18.32 18.98 19.40 19.7 20.48 21.00 21.00 21.16 21.4 
## 3 8 10.4 11.27 13.90 14.66 15.04 15.2 15.44 15.86 16.76 18.28 19.2 

Con ulteriori indagini sul motivo per cui questo funziona, sembra che data_frame_ differenzia dalle solite logiche SE utilizzati in dplyr. data_frame_ accetta un solo argomento columns e si aspetta davvero un argomento lazy_dots.

Se riceve un vettore, funziona, perché la valutazione lenta dei singoli argomenti funziona. Quindi questa caratteristica dell'uso di data_frame_ su un vettore del genere potrebbe effettivamente essere un bug.

+0

Non sapevo che 'data_frame_' funziona in modo compatto. Buone informazioni! – akrun

+0

C'è un modo per generare l'output in forma estesa usando 'data_frame _()' allora? – Arun

+0

@Arun: si potrebbe usare 'lazy_dots', ma ciò sembra un po 'troppo complicato:' data_frame_ (lazyeval :: lazy_dots (quantile (. $ Mpg, probs = probs))) '. Non so di una soluzione più semplice. Ovviamente questo è equivalente a 'data_frame (quantile (. $ Mpg, probs = probs))'. – shadow