Я пытаюсь агрегировать свои данные, чтобы найти корреляции/шаблоны, и хочу узнать, как и где данные могут коррелировать. В частности, я хочу определить, сколько раз идентификатор (здесь называемый «элемент») появляется вместе. Есть ли способ узнать, сколько раз каждый (id) появляется вместе подряд?
Это для более крупного data.frame, который уже был очищен и агрегирован на основе этого конкретного запроса. В прошлом я пытался применить несколько функций агрегации, суммирования и фильтрации из таких пакетов, как «data.table», «dplyr» и «tidyverse», но не смог получить то, что ищу.
В разделе 3(Показать код) я предоставил минимальный воспроизводимый пример:
set.seed(1234)
random.people<-c("Bob","Tim","Jackie","Angie","Christopher")
number=sample(12345:12350,2000,replace = T)
item=sample(random.people,2000,replace=T)
sample_data <- data.frame(cbind(number,item), stringsAsFactors = FALSE)
Используя примеры здесь, я ожидал, что вывод будет идентифицировать все комбинации, в которых имена были объединены в число, и показать n (значение) - ожидая, что результаты будут выглядеть примерно так:
Pair value
Bob, Tim 2
Bob, Jackie 4
Bob, Angie 0
Этот вывод (то, что я надеюсь получить) скажет мне, что во всем df есть 2 раза, что Боб и Тим и 4 раза, что Боб и Джеки оба имеют одинаковый номер.
но фактический результат:
Error: Each row of output must be identified by a unique combination of keys.
Keys are shared for 2000 rows:
* 9, 23, 37, 164, 170, 180, 211...
Update: I thought of a..creative(?) solution - but hope someone can help with expedting it. I can locate all the numbers (column1) that are shared between two names using the following:
x1<-sample_data %>% dplyr::filter(item= = "Bob")
x2<-sample_data %>% dplyr::filter(item= = "Tim")
Bob<-x1[,1]
Tim<-x2[,1]
Reduce(intersect, list(Bob,Tim))
output:
[1] "12345" "12348" "12350" "12346" "12349" "12347"
Как я уже сказал, это отнимает очень много времени и потребует создания множества векторов и пересечения каждого (например, 1 вектор для каждого имени) и нескольких комбинаций.
Другие ответы по вашей ссылке, вероятно, сработали бы, если бы вы добавили distinct
в свой конвейер. Ваша ошибка показывает, что у нее были проблемы с распространением данных, потому что были дубликаты.
set.seed(1234)
random.people<-c("Bob","Tim","Jackie","Angie","Christopher")
number=sample(12345:22350,2000,replace = T) # I edited ur number here.
item=sample(random.people,2000,replace=T)
sample_data <- data.frame(cbind(number,item), stringsAsFactors = FALSE)
library(tidyverse)
sample_data %>%
# find out unique rows
distinct() %>%
# nest the data frame into nested tibble, so now you have
# a "data" column, which is a list of small data frames.
group_nest(number) %>%
# Here we use purrr::map to modify the list column. We want each
# combination counts only once despite the order, so we use sort.
mutate(data = map_chr(data, ~paste(sort(.x$item), collapse = ", "))) %>%
# the last two steps just count the numbers
group_by(data) %>%
count()
# A tibble: 21 x 2
# Groups: data [21]
data n
<chr> <int>
1 Angie 336
2 Angie, Bob 8
3 Angie, Bob, Christopher 2
4 Angie, Bob, Jackie 1
5 Angie, Christopher 16
6 Angie, Jackie 9
7 Angie, Tim 10
8 Bob 331
9 Bob, Christopher 12
10 Bob, Christopher, Jackie 1
# … with 11 more rows
Одно из возможных решений
Здравствуйте и спасибо, что помогли мне здесь. У меня проблемы с пониманием вывода. Это выглядит как df с одним obs: Не знаете, как это расшифровать:? Классы «grouped_df», «tbl_df», «tbl» и «data.frame»: 1 заб. из 2 переменных:
@ BuffsGrad16 Разве это не то, что вы ищете? Я только что изменил ваш пример и включил его в свой обновленный ответ. Вы можете проверить это.
есть идеи альтернативы dplyr::group_nest? Я надеялся, что это сработает, потому что моя компания медленно загружает обновления для пакетов, а версия (dplyr), которая у нас есть, не имеет этой функции (также не удается воссоздать функцию)
@BuffsGrad16 %>% group_by(number) %>% nest() %>%
Вот базовое решение R, основанное на table
-> aggregate
и потенциально неэффективный способ вставки имен вместе с помощью apply
.
tab_data <- data.frame(unclass(table(unique(sample_data))))
#table results in columns c(Angie.1, Bob.1, ...) - this makes it look better
names(tab_data) = sort(random.people)
library(network)
plot.network.default(as.network(tab_data))
tab_data$n <- 1
agg_data <- aggregate(n~., data = tab_data, FUN = length)
agg_data$Pair <- apply(agg_data[, -length(agg_data)], 1, function(x) paste(names(x[x!=0]), collapse = ', '))
agg_data[order(agg_data$Pair), c('Pair', 'n') ]
Pair n
1 Angie 336
3 Angie, Bob 8
7 Angie, Bob, Christopher 2
11 Angie, Bob, Jackie 1
5 Angie, Christopher 16
9 Angie, Jackie 9
15 Angie, Tim 10
2 Bob 331
6 Bob, Christopher 12
... truncated ...
Что касается производительности, на этом относительно небольшом наборе данных оно примерно в 9 раз быстрее, чем решение dplyr:
Unit: milliseconds
expr min lq mean median uq max neval
base_solution 9.4795 9.65215 10.80984 9.87625 10.32125 46.8230 100
dplyr_solution 78.6070 81.72155 86.47891 83.96435 86.40495 200.7784 100
Данные
set.seed(1234)
random.people<-c("Bob","Tim","Jackie","Angie","Christopher")
number=sample(12345:22350,2000,replace = T) # I edited ur number here.
item=sample(random.people,2000,replace=T)
sample_data <- data.frame(number,item, n = 1L, stringsAsFactors = FALSE)
Спасибо @Коул. Я собираюсь попробовать это позже сегодня.
Вау, мне это очень нравится - чисто. Как вы думаете, возможно ли сделать это в сетевой матрице? У меня чертовски много времени с данными, потому что они слишком большие, а сетевой график (узлы, ребра) настолько высок, что его невозможно прочитать. Я пытался применить его только к сгруппированному выводу (например, к тому, что видно в вашем agg_data), но я не могу сформировать ребра, так как вывод для узлов равен двум (Pair, N)
Вы можете задать другой вопрос, но ближе ли network::plot.network.default(network::as.network(tab_data))
к желаемому результату? Я протестировал вызов до линии tab_data$n <- 1
, и у меня был сетевой график с 5 основными людьми, как и ожидалось. Однако график выглядел довольно сложным.
Хм, странно - ничего не возвращается (кроме «Ошибка в plot.network.default: нет функции макета для режима fruchtermanreingold»
Я отредактировал код, чтобы добавить вызов — см. строки 5 и 6.
Да, думаю, разошлись. Просто хочу: id номер, который используется совместно, и элемент (имена), которые его разделяют.