Как использовать expand.grid с условиями? - PullRequest
0 голосов
/ 06 апреля 2020

Я использую expand.grid из ряда переменных, но есть некоторые особые случаи, которые можно исключить. Поиск показал, что expand.grid не может этого сделать, но фильтры могут быть добавлены, так что вот моя попытка.

a = 1:5
b = 1:5
c = 0:3
d = 1:5
e = 1:3
df = expand.grid(a,b,c,d,e)
colnames(df)[c(1:5)] <- c("a","b","c","d","e");
df$d = ifelse(df$c == 0, d[[1]], df$d);
df$e = ifelse(df$c == 0, d[[1]], df$e);
df = unique(df)

В этом случае переменные d и e не используются, если c равно 0, поэтому я использую ifelse, чтобы установить d и e в первое значение d и e, если c = 0, а затем удалить дублирующиеся строки с уникальным.

Код выше действительно работает, так что с ним не так. Это слишком конкретно c.

Мне не нравятся 2 оператора ifelse для определенных c переменных. Что делать, если у меня есть 100 условных переменных. Как можно сжать оператор и, возможно, записать все условия или переменные, зависящие от какого-либо одного условия, только в одну строку.

Я также приветствую любые другие оптимизации для выполнения желаемой задачи с минимальным кодированием для сложного сценария ios. Спасибо.

Обновление

Что касается количества переменных, я просто не знаю до времени выполнения. Мой пример - очень простой случай. Очень часто я получаю отличные решения, но те, которые работают только для конкретного примера c, а не для настоящей проблемы.

У меня нет наборов от a до e или я знаю, сколько наборов или размер наборы у меня есть до времени выполнения. a может быть списком папок, списком вложенных папок, c файлами. но если файлы маленькие пустые или что-то еще, мне не нужно делать e и f.

Идеальное решение не смотрит на какие-либо значения stati c, такие как:

expand .grid (list_of_variables, key_variables = key_values, list_of_dependents)

Да, это выходит за рамки этого вопроса, но я просто хочу сказать, что решение должно работать с наборами данных, которые не были известны во время кодирования .

Надеюсь, это прояснит некоторые вещи вместо того, чтобы просто поднимать больше вопросов.

Ответы [ 2 ]

2 голосов
/ 06 апреля 2020

Мы можем использовать crossing

library(tidyr)
library(dplyr)
crossing(a, b, c, d, e) %>% 
    mutate_at(vars(d, e), ~ replace(., c == 0, first(.))) %>%
    distinct
1 голос
/ 06 апреля 2020

Вот еще один базовый способ R. Он использует логический индекс для изменения столбцов d и e, остальная часть кода похожа на вопрос. Тесты ниже показывают, что это самая быстрая альтернатива.

f1 <- function(a, b, c, d, e){
  X <- expand.grid(a, b, c, d, e)
  names(X) <- c("a","b","c","d","e")
  X$d <- ifelse(X$c == 0, X$d[1], X$d)
  X$e <- ifelse(X$c == 0, X$d[1], X$e)
  unique(X)
}

f2 <- function(a, b, c, d, e){
  X <- expand.grid(a, b, c, d, e)
  names(X) <- c("a","b","c","d","e")
  i <- X$c == 0
  X$d[i] <- X$d[1]
  X$e[i] <- X$e[1]
  unique(X)
}

library(tidyr)
library(dplyr)

f3 <- function(a, b, c, d, e){
  crossing(a, b, c, d, e) %>% 
    mutate_at(vars(d, e), ~ replace(., c == 0, first(.))) %>%
    distinct
}

a = 1:5
b = 1:5
c = 0:3
d = 1:5
e = 1:3

library(microbenchmark)

mb <- microbenchmark(
  op = f1(a,b,c,d,e),
  rui = f2(a,b,c,d,e),
  akrun = f3(a,b,c,d,e)
)

print(mb, unit = "relative", order = "median")
#Unit: relative
#  expr       min       lq     mean   median       uq      max neval cld
#   rui 1.0000000 1.000000 1.000000 1.000000 1.000000 1.000000   100  a 
#    op 0.8147996 1.035322 1.018649 1.026295 1.038269 1.096384   100  a 
# akrun 1.7580304 1.815582 1.836061 1.827887 1.872767 1.107545   100   b
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...