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

avatar
R.Hanovre
1 июля 2021 в 17:09
52
1
0

Я хочу подсчитать, как часто каждая попарная комбинация уникальных элементов в столбце c во фрейме данных df совпадает с элементами столбца a, но с добавлением того, что совпадения учитываются только в том случае, если соответствующие значения в столбце b не равны, т.е. зависят от несоответствия в столбце b

a <- c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4)
b <- c(1,1,2,2,2,1,1,2,2,3,3,3,3,1,1,1,2,2,2,4)
c <- c(1,2,1,2,3,2,3,1,2,1,1,2,3,1,2,1,1,2,4,1) 

df <- as.data.frame(cbind(a,b,c))

Без учета столбца b я мог бы сделать следующее, чтобы сохранить для каждой пары элементов столбца c, сколько элементов a они встречаются вместе

df <- unique(df[,c(1,3)])
df <- merge(df, df, by = "a")
df$count <- 1

df <- aggregate(count ~ .  df[, c(2:4)], sum)
df <- df[df$c.x != df$c.y,]

С дополнительным условием несоответствия в b есть только одно отличие: элементы 2 и 4 столбца c встречаются одновременно с элементом 4 столбца a, но имеют одинаковое значение в b и, следовательно, не должен учитываться как результат:

c.x <- c(2,3,4,1,3,1,2,1)
c.y <- c(1,1,1,2,2,3,3,4)
count <- c(4,3,1,4,3,3,3,1)

result <- as.data.frame(cbind(c.x,c.y,count))

Поскольку исходный набор данных большой (> 1 000 000 наблюдений), я приветствую быстрые решения, то есть без использования циклов или слияний. Обычно я создаю матрицы совпадений из фреймов данных с тремя столбцами, используя sparseMatrix()

Источник
akrun
1 июля 2021 в 17:12
0

Можете ли вы показать ожидаемый результат. Вам нужно crossprod(table(df[c(1, 3)]))

GuedesBF
1 июля 2021 в 17:30
0

Пожалуйста, уточните, что вы хотите. Как есть, ваш вопрос немного сбивает с толку

R.Hanovre
2 июля 2021 в 09:20
0

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

Ответы (1)

avatar
ktiu
1 июля 2021 в 17:39
0

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

library(purrr)

split(df, c) %>%
  combn(2, simplify = F) %>%
  set_names(map(.  ~ paste(names(.x), collapse = "_"))) %>%
  map_int(~ merge(.x[[1]], .x[[2]], by = NULL) %>%
            dplyr::filter(a.x == a.y && b.x != b.y) %>%
            nrow())

Возвраты:

1_2 1_3 1_4 2_3 2_4 3_4 
  0  27   0  21   0   0 
# Data used:
df <- structure(list(a = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4), b = c(1, 1, 2, 2, 2, 1, 1, 2, 2, 3, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4), c = c(1, 2, 1, 2, 3, 2, 3, 1, 2, 1, 1, 2, 3, 1, 2, 1, 1, 2, 4, 1)), class = "data.frame", row.names = c(NA, -20L))