Home > Enterprise >  Trying to pass a column from a tibble to a function that uses a data.table
Trying to pass a column from a tibble to a function that uses a data.table

Time:10-04

I am trying to write a function that will take in a tibble and a column name and then pass that to a data.table where the function will take place.

library(TidyDensity)
library(data.table)
library(tidyverse)

x <- mtcars$mpg

tb <- tidy_bootstrap(x) %>%
  bootstrap_unnest_tbl()

new_func <- function(.data, .x = y, .fns, .return_type = "tibble", ...){
  
  func <- .fns
  return_type <- .return_type
  args <- list(...)
  
  dt <- data.table::as.data.table(.data)
  
  ret <- data.table::melt(
    dt[, as.list(func(.x, unlist(args))), by = sim_number], 
    id.var = "sim_number",
    value.name = "quantile"
  ) %>%
    dplyr::as_tibble() %>%
    dplyr::arrange(sim_number, variable)
  
  return(ret)
}

new_func(tb, y, quantile, "tibble", probs=c(0.025,0.95))
 Error in func(.x, unlist(args)) : object 'y' not found

So it is obvious I am doing something wrong but I do not know what it is.

When I run the code not in a function it works wonderfully (func <- quantile):

data.table::melt(
    dt[, as.list(func(y, unlist(args))), by = sim_number], 
    id.var = "sim_number",
    value.name = "quantile"
  ) %>%
    dplyr::as_tibble() %>%
    dplyr::arrange(sim_number, variable)

# A tibble: 4,000 × 3
   sim_number variable quantile
   <fct>      <fct>       <dbl>
 1 1          2.5%         12.7
 2 1          95%          30.4
 3 2          2.5%         12.1
 4 2          95%          27.0
 5 3          2.5%         10.4
 6 3          95%          27.0
 7 4          2.5%         12.7
 8 4          95%          29.8
 9 5          2.5%         10.4
10 5          95%          30.4
# … with 3,990 more rows
# ℹ Use `print(n = ...)` to see more rows

CodePudding user response:

Convert the y to string and we could use .SDcols

new_func <- function(.data, .x = y, .fns, .return_type = "tibble", ...){
  
   func <- .fns
   .x <- deparse(substitute(.x))
   
   return_type <- .return_type
   args <- list(...)
   
  dt <- data.table::as.data.table(.data)
  
  ret <- data.table::melt(
     dt[, as.list(func(.SD[[1]], unlist(args))), by = sim_number, .SDcols = .x],
     
     id.var = "sim_number",
     value.name = "quantile"
   ) %>%
     dplyr::as_tibble() %>%
     dplyr::arrange(sim_number, variable)
  
   return(ret)
 }

-testing

out <- new_func(tb, y, quantile, "tibble", probs=c(0.025,0.95))
> head(out)
# A tibble: 6 × 3
  sim_number variable quantile
  <fct>      <fct>       <dbl>
1 1          2.5%         12.1
2 1          95%          30.4
3 2          2.5%         10.4
4 2          95%          33.6
5 3          2.5%         13.3
6 3          95%          30.4
  • Related