Передайте вектор имен переменных в range() в dplyr
Я хочу пройти arrange()
{dplyr} вектор имен переменных для сортировки. Обычно я просто набираю нужные переменные, но пытаюсь создать функцию, в которой переменные сортировки могут быть введены как параметр функции.
df <- structure(list(var1 = c(1L, 2L, 2L, 3L, 1L, 1L, 3L, 2L, 4L, 4L
), var2 = structure(c(10L, 1L, 8L, 3L, 5L, 4L, 7L, 9L, 2L, 6L
), .Label = c("b", "c", "f", "h", "i", "o", "s", "t", "w", "x"
), class = "factor"), var3 = c(7L, 5L, 5L, 8L, 5L, 8L, 6L, 7L,
5L, 8L), var4 = structure(c(8L, 5L, 1L, 4L, 7L, 4L, 3L, 6L, 9L,
2L), .Label = c("b", "c", "d", "e", "f", "h", "i", "w", "y"),
class = "factor")), .Names = c("var1", "var2", "var3", "var4"),
row.names = c(NA, -10L), class = "data.frame")
# this is the normal way to arrange df with dplyr
df %>% arrange(var3, var4)
# but none of these (below) work for passing a vector of variables
vector_of_vars <- c("var3", "var4")
df %>% arrange(vector_of_vars)
df %>% arrange(get(vector_of_vars))
df %>% arrange(eval(parse(text = paste(vector_of_vars, collapse = ", "))))
6 ответов
Хэдли не сделал этого очевидным в справочном файле - только в своей виньетке NSE. Версии функций, за которыми следуют подчеркивания, используют стандартную оценку, поэтому вы передаете им векторы строк и тому подобное.
Если я правильно понимаю вашу проблему, вы можете просто заменить arrange()
с arrange_()
и это будет работать.
В частности, передать вектор строк как .dots
аргумент, когда вы делаете это.
> df %>% arrange_(.dots=c("var1","var3"))
var1 var2 var3 var4
1 1 i 5 i
2 1 x 7 w
3 1 h 8 e
4 2 b 5 f
5 2 t 5 b
6 2 w 7 h
7 3 s 6 d
8 3 f 8 e
9 4 c 5 y
10 4 o 8 c
========== Обновление марта 2018 года ==============
Использование стандартных ознакомительных версий в dplyr, как я показал здесь , теперь считается устаревшим. Вы можете прочитать виньетку программирования Хэдли для нового пути. В основном вы будете использовать !!
расстаться с кавычками или !!!
расставить кавычки вектор переменных внутри arrange()
,
Когда вы пропустите эти столбцы, если они пустые, заключите их в кавычки, используя quo()
для одной переменной или quos()
для вектора. Не используйте кавычки. Смотрите ответ Акрун.
Если ваши столбцы уже являются строками, присвойте им имена, используя rlang::sym()
для одного столбца или rlang::syms()
для вектора. Смотрите ответ Христос. Вы также можете использовать as.name()
для одного столбца. К сожалению, на момент написания статьи, информация о том, как использовать rlang::sym()
еще не попал в виньетку, на которую я ссылаюсь выше (в конце концов, она будет в разделе "вариативная квазиквотация" согласно его проекту).
В духе цитат:
df %>% arrange(!!! rlang::syms(c("var1", "var3")))
Для одной переменной это будет выглядеть так:
df %>% arrange(!! rlang::sym(c("var1")))
В новой версии (скоро выйдет 0.6.0
из dplyr
) мы можем использовать quosures
library(dplyr)
vector_of_vars <- quos(var1, var3)
df %>%
arrange(!!! vector_of_vars)
# var1 var2 var3 var4
#1 1 i 5 i
#2 1 x 7 w
#3 1 h 8 e
#4 2 b 5 f
#5 2 t 5 b
#6 2 w 7 h
#7 3 s 6 d
#8 3 f 8 e
#9 4 c 5 y
#10 4 o 8 c
Когда существует более одной переменной, мы используем quos
и для одной переменной это quo
, quos
вернет list
цитируемых переменных и внутри arrange
мы цитируем list
с помощью !!!
для оценки
Я думаю, теперь ты можешь просто использовать dplyr::arrange_at()
.
library(dplyr)
### original
head(iris)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 5.1 3.5 1.4 0.2 setosa
# 2 4.9 3.0 1.4 0.2 setosa
# 3 4.7 3.2 1.3 0.2 setosa
# 4 4.6 3.1 1.5 0.2 setosa
# 5 5.0 3.6 1.4 0.2 setosa
# 6 5.4 3.9 1.7 0.4 setosa
### arranged
iris %>%
arrange_at(c("Sepal.Length", "Sepal.Width")) %>%
head()
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 4.3 3.0 1.1 0.1 setosa
# 2 4.4 2.9 1.4 0.2 setosa
# 3 4.4 3.0 1.3 0.2 setosa
# 4 4.4 3.2 1.3 0.2 setosa
# 5 4.5 2.3 1.3 0.3 setosa
# 6 4.6 3.1 1.5 0.2 setosa
It's a little dense, but I think the best approach now is to use
across()
along with a tidyselect function, e.g.
all_of()
:
df <- structure(list(var1 = c(1L, 2L, 2L, 3L, 1L, 1L, 3L, 2L, 4L, 4L
), var2 = structure(c(10L, 1L, 8L, 3L, 5L, 4L, 7L, 9L, 2L, 6L
), .Label = c("b", "c", "f", "h", "i", "o", "s", "t", "w", "x"
), class = "factor"), var3 = c(7L, 5L, 5L, 8L, 5L, 8L, 6L, 7L,
5L, 8L), var4 = structure(c(8L, 5L, 1L, 4L, 7L, 4L, 3L, 6L, 9L,
2L), .Label = c("b", "c", "d", "e", "f", "h", "i", "w", "y"),
class = "factor")), .Names = c("var1", "var2", "var3", "var4"),
row.names = c(NA, -10L), class = "data.frame")
vector_of_vars <- c("var3", "var4")
df %>% arrange(across(all_of(vector_of_vars)))
Попробуй это:
df %>% do(do.call(arrange_, . %>% list(.dots = vector_of_vars)))
и на самом деле это можно записать проще:
df %>% arrange_(.dots = vector_of_vars)
хотя на данный момент я думаю, что это то же самое, что подразумеваемое решение Фарнси.