Замена для `subset ()` для списка data.frames - PullRequest
1 голос
/ 21 октября 2019

Функция foo1 может подмножество (используя subset()) списка data.frames одной или несколькими запрошенными переменными (например, by = ESL == 1 или by == ESL == 1 & type == 4).

Однако яосознавая опасность использования subset() в R. Таким образом, мне интересно в foo1 ниже, что я могу использовать вместо subset() для получения того же результата?

foo1 <- function(data, by){

  s <- substitute(by)
  L <- split(data, data$study.name) ; L[[1]] <- NULL

  lapply(L, function(x) do.call("subset", list(x, s))) ## What to use instead of `subset`
                                                       ## to get the same output?
}

# EXAMPLE OF USE:
D <- read.csv("https://raw.githubusercontent.com/izeh/i/master/k.csv", header=TRUE) # DATA
foo1(D, ESL == 1) 

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Вы можете вычислить на языке. Основываясь на моем ответе на «Работа с заменой после $ входа в R» :

foo1 <- function(data, by){

  s <- substitute(by)
  L <- split(data, data$study.name) ; L[[1]] <- NULL

  E <- quote(x$a)
  E[[3]] <- s[[2]]
  s[[2]] <- E

  eval(bquote(lapply(L, function(x) x[.(s),])))
}

foo1(D, ESL == 1) 

Это становится более сложным для произвольных выражений подмножеств. Вам понадобится рекурсивная функция, которая сканирует дерево разбора и вставляет вызовы в $ в нужных местах.

Лично я бы просто использовал пакет data.table, где это проще, потому что вам не нужен $, то есть вы можете просто сделать eval(bquote(lapply(L, function(x) setDT(x)[.(s),]))) без изменения s. ОТО, я бы не стал этого делать. На самом деле нет причин для разделения перед поднабором.

1 голос
/ 21 октября 2019

Я бы предположил (основываясь на общих знаниях и кратком обзоре ответов на вопрос "Опасность подмножества ()" ), что опасности subset представляют собой внутренние опасности не-стандартная оценка (NSE);если вы хотите иметь возможность передать универсальное выражение и оценить его в контексте фрейма данных, я думаю, вы более или менее застряли с subset() или чем-то подобным.

Если бы вы былижелая использовать более ограниченный набор выражений, таких как var, vals (ищет случаи, когда переменная, индексированная строкой var принимает значения в векторе vals), вы можете использовать

d[d[[var]] %in% vals, ]

Здесь var является строкой , а не символом обнаженного R ("cyl" вместо cyl);однозначно, что вы хотите извлечь его из фрейма данных.

Вы можете расширить это на вектор переменных и список векторов значений:

for (i in seq_along(vars)) {
   d <- d[d[[vars[i]]] %in% vals[[i]], ]
}

, но если вы хотитеполная гибкость выражений (например, чтобы иметь возможность использовать ESL == 1 & type == 4 или ESL == 1 | type == 4 или неравенства, основанные на числовых переменных). Я думаю, что вы застряли с подходом на основе NSE.

Возможно, чтоНовый механизм "Tidy Eval" (в пакете rlang, подробно описанный здесь ) даст вам немного более принципиальный подход, но я не думаю, что опасности полностью исчезнут.

...