Как отфильтровать кадры данных на основе критериев в таблице? - PullRequest
1 голос
/ 27 марта 2020

Я воссоздал свою проблему, используя набор данных diamonds из ggplot2 в R.

Я хотел бы создать список (my_list), где каждый элемент в этом списке - это diamond фрейм данных, который имеет был отфильтрован по заданным c критериям, изложенным в таблице (analys).

Так, например:

my_list[[1]] будет иметь кадр данных diamonds, но только включая алмазы, где colour равно E или J. my_list[[2]] будет иметь фрейм данных diamonds, но только с бриллиантами, где clarity равен SI2 или VS1. my_list[[3]] будет иметь кадр данных diamonds, но только с бриллиантами, где cut равен Good или Very Good.

library(ggplot2)
diamonds = as.data.frame(diamonds)

# create a tibble with the list of filters I want
# eg, row 1 would mean I want only diamonds that have either the colour E or J.

analys <- tribble(
    ~column,   ~trt,   ~ctrl,       ~translation,
    "color",   "E",    "J",         "E vs J",
    "clarity", "SI2",  "VS1",       "SI1 vs VS1",
    "cut",     "Good", "Very Good", "Good vs Very Good")

# next create an empty list to populate
my_list = list()

# now create a function to filter diamonds dataframe, keeping only the entries where,
# for example the colour would be E or J (specified in the analys tibble).
my_list <- apply(analys, 1, function(x) subset(
    diamonds,
    x[["column"]] %in% c(x[["trt"]], x[["ctrl"]])
    )
)

Однако указанная выше функция не работает при использовании x [["column"]]. Может кто-нибудь исправить эту функцию, чтобы она работала?

Ответы [ 2 ]

2 голосов
/ 27 марта 2020

Вот способ использования некоторой нестандартной оценки:

library(dplyr)

apply_fun <- function(data, col, value1, value2) {
   data %>% filter(!!sym(col) %in% c(value1, value2))
}

temp <- apply(analys, 1, function(x) 
              apply_fun(diamonds, x[['column']], x[['trt']], x[['ctrl']]))

head каждого списка выглядит так:

lapply(temp, head)
#[[1]]
#  carat       cut color clarity depth table price    x    y    z
#1  0.23     Ideal     E     SI2  61.5    55   326 3.95 3.98 2.43
#2  0.21   Premium     E     SI1  59.8    61   326 3.89 3.84 2.31
#3  0.23      Good     E     VS1  56.9    65   327 4.05 4.07 2.31
#4  0.31      Good     J     SI2  63.3    58   335 4.34 4.35 2.75
#5  0.24 Very Good     J    VVS2  62.8    57   336 3.94 3.96 2.48
#6  0.22      Fair     E     VS2  65.1    61   337 3.87 3.78 2.49

#[[2]]
#  carat       cut color clarity depth table price    x    y    z
#1  0.23     Ideal     E     SI2  61.5    55   326 3.95 3.98 2.43
#2  0.23      Good     E     VS1  56.9    65   327 4.05 4.07 2.31
#3  0.31      Good     J     SI2  63.3    58   335 4.34 4.35 2.75
#4  0.23 Very Good     H     VS1  59.4    61   338 4.00 4.05 2.39
#5  0.23     Ideal     J     VS1  62.8    56   340 3.93 3.90 2.46
#6  0.31     Ideal     J     SI2  62.2    54   344 4.35 4.37 2.71

#[[3]]
#  carat       cut color clarity depth table price    x    y    z
#1  0.23      Good     E     VS1  56.9    65   327 4.05 4.07 2.31
#2  0.31      Good     J     SI2  63.3    58   335 4.34 4.35 2.75
#3  0.24 Very Good     J    VVS2  62.8    57   336 3.94 3.96 2.48
#4  0.24 Very Good     I    VVS1  62.3    57   336 3.95 3.98 2.47
#5  0.26 Very Good     H     SI1  61.9    55   337 4.07 4.11 2.53
#6  0.23 Very Good     H     VS1  59.4    61   338 4.00 4.05 2.39

Если вы хотите остаться в tidyverse, вы можете использовать pmap, который добавит столбец списка в analys сам фрейм данных.

analys %>%
  mutate(temp = purrr::pmap(list(column, trt, ctrl), 
                  ~apply_fun(diamonds, ..1, ..2, ..3)))

# A tibble: 3 x 5
#  column  trt   ctrl      translation       temp                   
#  <chr>   <chr> <chr>     <chr>             <list>                 
#1 color   E     J         E vs J            <df[,10] [12,605 × 10]>
#2 clarity SI2   VS1       SI1 vs VS1        <df[,10] [17,365 × 10]>
#3 cut     Good  Very Good Good vs Very Good <df[,10] [16,988 × 10]>
1 голос
/ 27 марта 2020

Как отметил @Ronak, у вас есть несколько вариантов, чтобы сделать эту работу. По сути, вам нужно, чтобы x[["column"]] рассматривался как символ.

Вот еще один способ заставить эту работу работать с использованием вашей функции. Вы можете построить выражение как строку отдельно с помощью parse_expr, а затем использовать eval в subset:

my_list <- apply(analys, 1, function(x) {
  ex <- parse_expr(paste0(x[["column"]], "%in% c('", x[["trt"]], "','", x[["ctrl"]], "')"))
  subset(diamonds, eval(ex))
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...