Ответ 1
Я понял это через пробную версию и ошибку. Если кто-то любопытен, сделал что-то вроде этого:
lapply(names.gens, as.name)
select(df.main.scaled, eval(names.gens[[i]]), eval(names.gens[[i+someindex]]))
Я пробовал искать, но не нашел ответа на этот вопрос.
Я пытаюсь использовать оператор select в dplyr, но у меня возникают проблемы при попытке отправить его. Мой вопрос: как я могу указать select(), что строка, которую он видит, является именем столбца в кадре данных?
например. это прекрасно работает
select(df.main.scaled, var1, var3)
select(df.main.scaled, var2, var4)
но это не работает:
select(df.main.scaled, names.gens[i,1], names.gens[i,2])
где
> names.genx <- c("var1","var2")
> names.geny <- c("var3","var4")
> names.gens <- cbind(names.genx, names.geny)
> names.gens
names.genx names.geny
[1,] "var1" "var3"
[2,] "var2" "var4"
Чтобы быть ясным, все строки в именах .gens - это имена столбцов в фрейме данных.
Спасибо.
Я понял это через пробную версию и ошибку. Если кто-то любопытен, сделал что-то вроде этого:
lapply(names.gens, as.name)
select(df.main.scaled, eval(names.gens[[i]]), eval(names.gens[[i+someindex]]))
Выберите, кажется, работает с индексами столбцов (dplyr 0.2), поэтому просто сопоставьте свои имена с их индексом и используйте их для выбора столбцов.
myCols <- c("mpg","disp")
colNums <- match(myCols,names(mtcars))
mtcars %>% select(colNums)
В более поздних версиях dplyr это возможно в select
с one_of
, как в
my_cols <- c('mpg', 'disp')
mtcars %>% select(one_of(my_cols))
Я столкнулся с этим, и я подумал, что должен упомянуть, что это было решено в более новых версиях dplyr.
myTest = data_frame(
var1 = 1,
var2 = 2,
var3 = 3,
var4 = 4)
i = 1
myTest %>%
select_(.dots =
c(names.gens[i,1], names.gens[i,2]) %>% unname)
Вы можете использовать get()
, чтобы получить объект, названный строкой в текущей среде. Итак:
R> iris %>% select(Species, Petal.Length) %>% head(3)
Species Petal.Length
1 setosa 1.4
2 setosa 1.4
3 setosa 1.3
R> iris %>% select('Species', 'Petal.Length') %>% head(3)
Error in abs(ind[ind < 0]) :
non-numeric argument to mathematical function
R> iris %>% select(get('Species'), get('Petal.Length')) %>% head(3)
Species Petal.Length
1 setosa 1.4
2 setosa 1.4
3 setosa 1.3
R> s <- 'Species'
R> p <- 'Petal.Length'
R> iris %>% select(get(s), get(p)) %>% head(3)
Species Petal.Length
1 setosa 1.4
2 setosa 1.4
3 setosa 1.3
[Изменить - некоторые из приведенных ниже устарели с выпуском dplyr 0.7 - см. здесь]
Вопрос о разнице между стандартной оценкой и нестандартной оценкой.
tl; dnr: Вы можете использовать аналог "стандартной оценки" dplyr::select
, который равен dplyr::select_
.
Это позволяет вам указывать имена столбцов в виде переменных, содержащих строки:
dplyr::select_(df.main.scaled, names.gens[i,1], names.gens[i,2])
Вот несколько деталей, которые пытаются объяснить, как это работает:
Нестандартная оценка - это оценка кода нестандартными способами. Часто это означает захват выражений до их оценки и оценку их в другой среде (контексте/сфере) до нормального. Когда вы указываете dplyr::select
имена столбцов без кавычек, dplyr
использует нестандартную оценку, чтобы интерпретировать их как столбцы.
Предположим, что у нас есть следующий фрейм данных:
df <- tibble::data_frame(a = 1:5, b = 6:10, c = 11:15, d = 16:20)
Простой пример оператора select выглядит следующим образом:
r <- dplyr::select(df, a, b)
Это пример NSE, потому что a и b не являются переменными, которые существуют в глобальной среде. Вместо поиска a и b в глобальном пространстве имен dplyr::select
направляет R для поиска переменных a и b в контексте dataframe df
. Вы можете думать о том, что среда немного похожа на список, а a и b - на клавиши. Итак, следующее немного похоже на поиск R для поиска df$a
и df$b
Аргументы функции в R promises, которые не оцениваются немедленно. Они могут быть захвачены как выражения, а затем выполняться в другой среде.
Это прекрасно, если мы знаем, что мы хотим заранее выбрать столбцы a
и b
. Но что, если эти столбцы неизвестны заранее и хранятся в переменной.
columns_to_select <- c("a", "b")
Не работает следующее:
dplyr::select(df, columns_to_select)
Эта ошибка говорит нам, что в кадре данных нет столбца, называемого "columns_to_select". Аргумент columns_to_select
был оценен в контексте фрейма данных, поэтому R попытался сделать что-то вроде df$columns_to_select
и обнаружил, что столбец не существует.
Как мы это исправим?
Функции Tidyverse всегда обеспечивают 'escape hatch', которые позволяют обойти это ограничение. dplyr vignette говорит:" Каждая функция dplyr, использующая NSE, также имеет версию, использующую SE. Имя версии SE всегда является именем NSE с _ в конце. '
Что это значит?
Мы можем попробовать следующее, но мы обнаруживаем, что оно не работает:
# Does not work
r <-dplyr::select_(df, columns_to_select)
В отличие от захвата аргумента columns_to_select
функции select_ и интерпретации его как имени столбца, columns_to_select
оценивается стандартным способом, разрешая c("a", "b")
.
Это то, что мы хотим, за исключением того, что каждый аргумент select_
является единственным столбцом, и мы просто предоставили вектор символов длины два для представления одного столбца.
Таким образом, приведенный выше код возвращает кусочек с одним столбцом, а это не то, что мы хотели. (Используется только первый элемент - "a"
в символьном векторе, все остальное игнорируется).
Одно из решений этой проблемы заключается в следующем, но предполагает, что columns_to_select
содержит ровно два элемента:
col1 <- columns_to_select[1]
col2 <- columns_to_select[2]
r <- dplyr::select_(df,col1, col2)
Как мы обобщаем это на случай, когда columns_to_select
может иметь произвольное количество элементов?
Решение состоит в использовании необязательного аргумента .dots
.
dplyr::select_(df, .dots=columns_to_select)
Это имеет некоторое объяснение
В R конструкция ...
позволяет создавать функции с переменным (произвольным) числом аргументов. ...
доступен внутри функции и позволяет тело функции получить доступ ко всем аргументам. См. Также здесь.
Очень простой пример:
addition <- function(...) {
args <- list(...)
sum(unlist(args))
}
r <- addition(1,2,3)
Однако это не сразу помогает нам здесь. Он фактически уже реализован в функции select_
и просто позволяет нам предоставить произвольное количество имен столбцов в качестве аргументов, например. select_(df, "a", "b", "c", "d")
.
Нам нужен механизм, похожий на ...
, но позволяющий передать что-то вроде ...
в функцию как один аргумент. Это именно то, что делает .dots
.
Обратите внимание, что .dots
не предоставляется select
, поскольку он предназначен для интерактивного использования.
В dplyr 0.1.2 существует обходное решение с использованием регулярных выражений и совпадений (см. комментарий к файлу ниже для получения информации о прямой поддержке в будущих версиях). Регулярное выражение, такое как ^(x1|x2|x3)$
, соответствует именам точных переменных, поэтому нам просто нужно построить такое выражение из вектора с именами переменных. Вот код
# load libraries
library(dplyr)
library(stringr)
# create data.frame
df = data.frame(
x = rep(0,5),
y = 1,
var = 2,
another_var = 5,
var.4 = 6
)
# function to construct reg exp from vector with variable names
varlist = function(x) {
x = str_c('^(',paste(x, collapse='|'),')$')
x = str_replace_all(x,'\\.','\\\\.')
return(x)
}
# select variables based on vector of variable names
vars = c('y','another_var','var.4')
df %.%
select(matches(varlist(vars)))