У меня есть база данных значений символов.
df = data.frame(col1 = c("value_1","value_3","value_3","value_2"),
col1 = c("value_1","value_1","value_4","value_2"),
col1 = c("value_1","value_2","value_1","value_2"),
col1 = c("value_3","value_3","value_3","value_2"),
col1 = c("value_2","value_3","value_4","value_2"))
Я хочу подсчитать, сколько раз комбинация значений присутствует подряд. Комбинация не точная, например, если мне нужна комбинация значения_1 и значения_2, это комбинация наличия обоих значений ПО МИНИМУМ один раз. Комбинация является входными данными, и количество элементов во входных данных может быть разным.
Вход:
comb = c("value_1","value_2")
Желаемый результат
out = 2
Одним из решений является использование функции ifelse() для каждой модальности в гребенке, путем цикла по количеству элементов в гребенке, создания фиктивной переменной для каждого элемента, получения продукта каждого, а затем просто суммирования продукта.
Но мне интересно, есть ли более элегантное решение?
Вот быстрый способ:
df <- data.frame(col1 = c("value_1","value_3","value_3","value_2"),
col1 = c("value_1","value_1","value_4","value_2"),
col1 = c("value_1","value_2","value_1","value_2"),
col1 = c("value_3","value_3","value_3","value_2"),
col1 = c("value_2","value_3","value_4","value_2"))
comb <- c("value_1","value_2")
apply(df, 1, function(x) all(comb %in% x)) |>
sum()
Обратите внимание, что это приведет к внутреннему преобразованию df
в матрицу, чтобы apply
мог обрабатывать каждую строку. Могут быть более быстрые/эффективные способы сделать это (возможно, используя одну из функций map
из пакета purrr
).
Использование rowSums
дважды:
> sum(rowSums(combn[1L]==df) * rowSums(combn[2L]==df) > 0L)
[1] 2
Завершение в функцию f
:
f = \(df, combn) {
stopifnot(is.data.frame(df), is.character(combn), length(combn)==2L)
sum(rowSums(combn[1L]==df) * rowSums(combn[2L]==df) > 0L)
}
f(df, combn)
# [1] 2
Если ваш comb
всегда состоит из 2
элементов, вы можете попробовать match
+ rowMeans
, как показано ниже.
sum(
!rowMeans(
`dim<-`(match(as.matrix(df), comb), dim(df)),
TRUE
) %in% seq_along(comb)
)
Или, для общей длины comb
, вы можете использовать
sum(
rowMeans(
apply(
outer(as.matrix(df), comb, `==`),
3,
rowSums
) > 0
) == 1
)