Quosure с вложенной функцией - PullRequest
0 голосов
/ 02 ноября 2018

Я изо всех сил пытаюсь написать функцию fun2 , которая использует fun1 ... и продолжает получать ошибки. Я написал упрощенный пример ниже. Это первый раз, когда я имею дело с «аккуратной оценкой» и не уверен, что понимаю все ее плюсы.

Пример кадра данных:

d1 = data.frame(
  ID = c("A", "A", "A", "B", "B", "C", "C", "C", "C"),
  EXPR = c(2, 8, 3, 5, 7, 20, 1, 5, 4)
)

d2 = data.frame(
  ID = c("A", "B", "C"),
  NUM = c(22, 50, 31)
)

Первая функция

fun1 <- function(
  df1 = "df 1", 
  df2 = "df 2",
  t1 = "threshold 1",
  expr_col = "expr column", 
  id_col = "sample column - must be present in df1 and df2") {

  # dataframes
  df <- df1
  db <- df2

  # quosure
  enquo_id <- enquo(id_col)
  enquo_expr <- enquo(expr_col)

  # classify
  df <- df %>% 
    mutate(threshold = t1) %>% 
    mutate(class = ifelse(!!enquo_expr > t1, "positive", "negative")) %>% 
    mutate(class = factor(class, levels = c("positive", "negative")))

  # calculate sample data
  df.sum <- df %>% 
    group_by(!!enquo_id, class) %>% 
    summarise(count = n()) %>% 
    complete(class, fill = list(count = 0)) %>% 
    mutate(total = sum(count), freq = count/total)

  # merge dataframes
  df.sum <- left_join(df.sum, db, by = quo_name(enquo_id))

  # return
  return(df.sum)
}

Если я выполню тест этого, я получу в ответ фрейм данных, как и ожидалось

test <- fun1(df1 = d1, df2 = d2, t1 = 3, expr_col = EXPR, id_col = ID)

Вторая функция Теперь с fun2 я пытаюсь использовать fun1 в цикле for для итерации от ti до tf вектора seq:

fun2 <- function(
  df1 = "df 1", 
  df2 = "df 2",
  expr_col = "expr column", 
  id_col = "sample column - must be present in df1 and df2",
  ti = "initial value",
  tf = "final value",
  res = "resolution") {

  # define variables for fun1
  var1 <- enquo(d1)
  var2 <- enquo(d2)
  var3 <- enquo(t1)
  var4 <- enquo(EXPR)
  var5 <- enquo(ID)

  # get sequence of values
  seq <- seq(from = ti, to = tf, by = res)

  # open list
  t.list <- list()

  # Loop ----
  for (i in seq_along(seq)){
    t1 <- seq[i]
    t.list[[i]] <- fun1(df1 = var1,
                        df2 = var2,
                        t1 = var3,
                        expr_col = var4,
                        id_col = var5)
  }
  df.out <- plyr::ldply(t.list, rbind)

  ### Return ---
  return(df.out)
}

Но если я запущу это

test <- fun2(df1 = d1, df2 = d2, expr_col = EXPR, id_col = ID, ti = 1, tf = 10, res = 1)

Я получаю сообщение об ошибке

Error in (function (x)  : object 'EXPR' not found

Я пробовал разные вещи ... и я застрял здесь. Я полагаю, что не правильно использую enquo () . Я могу заставить его работать, не используя varX и вставляя непосредственно фактическое соответствующее имя каждого элемента в аргументы fun1 , но весь смысл сделать это, для меня, состоит в том, чтобы сделайте его " generalisable " и, следовательно, укажите аргументы только в fun2 , которые затем будут переданы в fun1 .

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 02 ноября 2018

Большое спасибо за ответ Аосмит. Теперь я сортируюсь, используя следующий код:

fun2 <- function(
  df1 = "df 1", 
  df2 = "df 2",
  expr_col = "expr column", 
  id_col = "sample column - must be present in df1 and df2",
  ti = "initial value",
  tf = "final value",
  res = "resolution") {

  # define variables for fun1
  var4 <- enquo(expr_col)
  var5 <- enquo(id_col)

  # get sequence of values
  seq <- seq(from = ti, to = tf, by = res)

  # open list
  t.list <- list()

  ### Loop --------------------------------------------------------------
  for (i in seq_along(seq)){
    t1 <- seq[i]
    t.list[[i]] <- fun1(df1 = df1,
                        df2 = df2,
                        t1 = t1,
                        expr_col = !!var4,
                        id_col = !!var5)
  }
  df.out <- plyr::ldply(t.list, rbind)

  ### Return ---
  return(df.out)
}

# TEST FUN2
test <- fun2(df1 = d1, df2 = d2, expr_col = EXPR, id_col = ID, ti = 1, tf = 10, res = 1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...