Как я могу создать data.frame на основе переменного количества входных данных - PullRequest
0 голосов
/ 06 июля 2018

Прежде всего, извините за несколько неинформативный заголовок

У меня есть блестящее приложение, в котором пользователь загружает один из множества возможных наборов данных и для некоторых столбцов может выполнить фильтр для вывода вывода data.frame

Я хочу стандартизировать код независимо от загруженного набора данных

Проблема в том, что имена столбцов различаются по набору данных, и будет иметь место переменное число столбцов, которые я хочу отфильтровать на

Что касается создания входных данных, я адаптировал это решение , используя подход tidyeval. Однако у меня возникли проблемы с выводом без необходимости прибегать к множеству операторов if else, основанных на количестве столбцов, которые можно отфильтровать по

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

library(tidyverse)

## desired columns 
my_cols <- c("col 1", "another col")

# selected input
input_1 <- c("A","B")
input_2 <- c("Z")

l <- list(`col 1` = rep(c("A","B","C"),times=3), `another col` = 
rep(c("X","Y","Z"),each=3), Value = c(1:9),`Unwanted 1`=(9:1))

df <- as_tibble(l)

# this creates the right number of correctly-named columns
for (i in seq_along(my_cols)) {
assign(paste0("col_", i), sym(my_cols[i]))
}

## This produces output but wish to adapt
## to varying number of columns

df %>%
filter(!!col_1 %in% input_1) %>%
filter(!!col_2 %in% input_2) %>%
select(!!col_1, !!col_2, Value)

#  `col 1` `another col` Value
#  <chr>   <chr>         <int>
# 1 A       Z                 7
# 2 B       Z                 8

Так что это последний кусок кода, который я хочу адаптировать для учета переменной длины my_cols

ТИА

1 Ответ

0 голосов
/ 06 июля 2018

Вы, похоже, храните входные данные в отдельных переменных, предлагая заранее знать, сколько столбцов будет обрабатываться (если только они не получены из динамически генерируемого пользовательского интерфейса). В любом случае, я предлагаю вам также хранить входные данные в одном объекте (надеюсь, такой же длины, как my_cols, в противном случае вы можете задать поднабор списка входных данных для соответствия длине вектора my_cols). Затем вы можете подготовить список предложений и разделить их на filter и select.

library(tidyverse)
library(rlang)

## desired columns 
my_cols <- c("col 1", "another col")

# selected input
input_1 <- c("A","B")
input_2 <- c("Z")
input_3 <- NULL # ui handle that is not used for this dataset

l <- list(`col 1` = rep(c("A","B","C"),times=3), `another col` = 
            rep(c("X","Y","Z"),each=3), Value = c(1:9),`Unwanted 1`=(9:1))

df <- as_tibble(l)

# make a list of inputs
l_input <- list(input_1, input_2, input_3)[seq_along(my_cols)]

# make a list of expression quosures. Make sure you use enquos if inside function 
l_expr <- mapply(function(x,y) quos(!!sym(x) %in% !!y), my_cols, l_input, USE.NAMES = F)
# splice into filter and select
df %>% filter(!!!l_expr) %>%  select(!!!syms(my_cols), Value)

Если вы поместите это внутри функции, не забудьте использовать enquos()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...