2014-09-11 15 views
10

Sono interessato all'utilizzo di dplyr per creare repliche di bootstrap (analisi ripetute in cui i dati vengono prima campionati con sostituzione ogni volta). Hadley Wickham here fornisce un codice per la ripetizione analisi bootstrap in modo efficiente:Utilizzo di dplyr's do per eseguire le repliche di bootstrap

bootstrap <- function(df, m) { 
    n <- nrow(df) 

    attr(df, "indices") <- replicate(m, sample(n, replace = TRUE), 
    simplify = FALSE) 
    attr(df, "drop") <- TRUE 
    attr(df, "group_sizes") <- rep(n, m) 
    attr(df, "biggest_group_size") <- n 
    attr(df, "labels") <- data.frame(replicate = 1:m) 
    attr(df, "vars") <- list(quote(boot)) # list(substitute(bootstrap(m))) 
    class(df) <- c("grouped_df", "tbl_df", "tbl", "data.frame") 

    df 
} 

library(dplyr) 
mboot <- bootstrap(mtcars, 10) 

# Works 
mboot %.% summarise(mean(cyl)) 

Mentre questa funzione funziona bene per summarise, non funziona per do quando do contiene un data.frame. (Immaginate per ora che data.frame contenga qualcosa di utile come i risultati dell'analisi che desideriamo eseguire il bootstrap).

bootstrap(mtcars, 3) %>% do(data.frame(x=1:2)) 
# Error: index out of bounds 

con il traceback

11: stop(list(message = "index out of bounds", call = NULL, cppstack = NULL)) 
10: .Call("dplyr_grouped_df_impl", PACKAGE = "dplyr", data, symbols, 
     drop) 
9: grouped_df_impl(data, unname(vars), drop) 
8: grouped_df(cbind_list(labels, out), groups) 
7: label_output_dataframe(labels, out, groups(.data)) 
6: do.grouped_df(`bootstrap(mtcars, 3)`, data.frame(x = 1:2)) 
5: do(`bootstrap(mtcars, 3)`, data.frame(x = 1:2)) 
4: eval(expr, envir, enclos) 
3: eval(e, env) 
2: withVisible(eval(e, env)) 
1: bootstrap(mtcars, 3) %>% do(data.frame(x = 1:2)) 

ero in grado di ovviare a questo eseguendo due do passi e un gruppo da:

bootstrap(mtcars, 10) %>% do(d=data.frame(x=1:2)) %>% group_by(replicate) %>% do(.$d[[1]]) 

ma ciò sembra richiedere un sacco di più , e in qualche modo maldestri, passi (e riceve anche un avvertimento, Grouping rowwise data frame strips rowwise nature). Sono anche consapevole del fatto che ho potuto replicare i dati in dieci repliche prima con qualcosa di simile

data.frame(boot=1:10) %>% group_by(boot) %>% do(sample_n(mtcars, nrow(mtcars), replace=TRUE)) 

ma se i dati o il numero di bootstrap replica è grande questo è estremamente inefficiente in memoria.

C'è un modo, forse modificando la funzione di installazione bootstrap, che posso eseguire queste repliche con bootstrap(mtcars, 3) %>% do(data.frame(x = 1:2))?

risposta

6

Penso che sia un piccolo bug nella funzione bootstrap. L'attributo vars deve corrispondere al nome della colonna nello data.frame nell'attributo labels. Ma nella funzione, l'attributo vars si chiama "boot" e il nome della colonna è replicate. Quindi, se fate questo piccolo cambiamento:

bootstrap <- function(df, m) { 
    n <- nrow(df) 

    attr(df, "indices") <- replicate(m, sample(n, replace = TRUE), 
            simplify = FALSE) 
    attr(df, "drop") <- TRUE 
    attr(df, "group_sizes") <- rep(n, m) 
    attr(df, "biggest_group_size") <- n 
    attr(df, "labels") <- data.frame(replicate = 1:m) 
    attr(df, "vars") <- list(quote(replicate)) # Change 
# attr(df, "vars") <- list(quote(boot)) # list(substitute(bootstrap(m))) 
    class(df) <- c("grouped_df", "tbl_df", "tbl", "data.frame") 

    df 
} 

allora funziona come previsto:

bootstrap(mtcars, 3) %>% do(data.frame(x=1:2)) 
# Source: local data frame [6 x 2] 
# Groups: replicate 

# replicate x 
# 1   1 1 
# 2   1 2 
# 3   2 1 
# 4   2 2 
# 5   3 1 
# 6   3 2 
Problemi correlati