Создание всех возможных комбинаций предметов и выполнение расчетов одновременно - PullRequest
0 голосов
/ 10 октября 2018

Я новичок в программировании на R и, следовательно, борюсь с кодом, который мне нужно написать.

Предположим, у меня есть матрица элементов (в столбцах) с некоторыми значениями для каждого случая, подобного этому -

enter image description here

Я хочусформировать различные комбинации этих элементов столбца, а именно.комбинации из двух предметов, комбинации из трех предметов и так далее.В то же время я хочу выполнить некоторые вычисления для каждой из этих комбинаций, используя значения из предыдущей таблицы (вставлено выше).Я сделал это в Excel для комбинаций из двух -

enter image description here

Но формула меняется для разных комбинаций, т.е. для комбинации двух элементов, формула будет

(exp (item1) + exp (item2)) / (exp (item1) + exp (item2) + 4)

Для комбинации из 3 элементовформула будет расширяться следующим образом:

(exp (item1) + exp (item2) + exp (item3)) / (exp (item1) + exp (item2) + exp (item3) + 4)

И так далее ...

Я выяснил, что комбинации могут быть сформированы с использованием comboGeneral в пакете R RcppAlgos или turf.combos в упаковке turfR.Однако я не могу понять, как я могу одновременно выполнять вычисления в одном R-коде, а также делать код динамическим (из-за изменения структуры формулы, упомянутой выше).Пожалуйста, помогите.

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Вот общее решение.Я использовал красиво предоставленный скрипт генерации данных от Jon Spring (хотя я сократил его размер в иллюстративных целях).

# function to do your calculation
foo = function(x) sum(exp(x)) / sum(exp(x), 4)

# generate combinations (only base functions needed)
n_items = 5
combos = lapply(2:n_items, function(x) combn(1:n_items, x, simplify = FALSE))
combos = unlist(combos, recursive = FALSE)

# convert input to a matrix and only keep Item columns.
mat = as.matrix(df_wide[, -1])
# set up matrix to hold results
results = matrix(NA_real_, nrow = nrow(mat), ncol = length(combos))

# iterate over the combinations and use apply to calculate foo row-wise
# for each combination of columns
for (i in seq_along(combos)) {
  results[, i] = apply(mat[, combos[[i]]], MARGIN = 1, FUN = foo)
}

# name results and add them to the original data
colnames(results) = sapply(combos, paste, collapse = "_")
final_result = cbind(df_wide, results)

# see what we've got
print(final_result[, 1:27], digits = 3)
#   ID Item1 Item2 Item3 Item4  Item5   1_2   1_3   1_4   1_5   2_3   2_4   2_5   3_4
# 1  1 0.915 0.519 0.458 0.940 0.9040 0.511 0.505 0.558 0.554 0.449 0.515 0.509 0.509
# 2  2 0.937 0.737 0.719 0.978 0.1387 0.537 0.535 0.566 0.481 0.509 0.543 0.447 0.541
# 3  3 0.286 0.135 0.935 0.117 0.9889 0.382 0.492 0.380 0.501 0.480 0.362 0.489 0.479
# 4  4 0.830 0.657 0.255 0.475 0.9467 0.514 0.473 0.494 0.549 0.446 0.469 0.530 0.420
# 5  5 0.642 0.705 0.462 0.560 0.0824 0.495 0.466 0.477 0.427 0.474 0.486 0.437 0.455
#     3_5   4_5 1_2_3 1_2_4 1_2_5 1_3_4 1_3_5 1_4_5 2_3_4 2_3_5 2_4_5 3_4_5 1_2_3_4
# 1 0.503 0.557 0.590 0.627 0.624 0.624 0.621 0.653 0.593 0.589 0.627 0.623   0.675
# 2 0.445 0.488 0.626 0.646 0.591 0.645 0.590 0.614 0.630 0.569 0.596 0.594   0.700
# 3 0.567 0.488 0.557 0.474 0.563 0.556 0.621 0.563 0.546 0.615 0.553 0.614   0.606
# 4 0.492 0.511 0.580 0.593 0.630 0.565 0.606 0.618 0.547 0.592 0.605 0.578   0.640
# 5 0.401 0.415 0.579 0.587 0.556 0.567 0.533 0.542 0.573 0.540 0.549 0.525   0.645
## ...    

Используя этот пример данных:

library(dplyr); library(tidyr)
set.seed(42)
df <- data_frame(ID   = rep(1:5, 5),
                   Item = rep(paste0('Item', 1:5), each = 5),
                   value = runif(25))
df

df_wide <- df %>% spread(Item, value)
0 голосов
/ 10 октября 2018

Я думаю, что общее решение для n предметов мне не подходит, но оно должно быть выполнимым.

Во-первых, некоторые поддельные данные:

#   (BTW, it would be more helpful to provide this as text in your question.)
library(dplyr); library(tidyr)
set.seed(42)
df <- data_frame(ID   = rep(1:100, 5),
                   Item = rep(1:5, each = 100),
                   value = runif(500))
df

# I've made it in "long" format, but we can show in wide format like this
df_wide <- df %>% spread(Item, value)
df_wide

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

output_tbl <- df %>%
  group_by(ID) %>%
  crossing(.$Item, .$Item) %>%
  ungroup() %>%
  select(-Item, -value) %>%
  left_join(df, by = c("ID" = "ID", 
                         '.$Item' = "Item")) %>%
  left_join(df, by = c("ID" = "ID", 
                         ".$Item1" = "Item")) %>%
  mutate(output = (exp(value.x) + exp(value.y)) / (exp(value.x) + exp(value.y) + 4))

А вот решение для всех комбинаций из трех предметов:

output_tbl <- df %>%
  group_by(ID) %>%
  crossing(.$Item, .$Item, .$Item) %>%
  ungroup() %>%
  select(-Item, -value) %>%
  left_join(df, by = c("ID" = "ID", 
                       '.$Item' = "Item")) %>%
  left_join(df, by = c("ID" = "ID", 
                       ".$Item1" = "Item")) %>%
  left_join(df, by = c("ID" = "ID", 
                       ".$Item2" = "Item")) %>%
  mutate(output = (exp(value.x) + exp(value.y) + exp(value)) / 
           (exp(value.x) + exp(value.y) + exp(value) + 4))
...