Нахождение взаимного пересечения двух множеств в двух разных фреймах данных, сгруппированных по некоторой переменной - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть два кадра данных:

* 1004 множество А *:

   session_id            datetime request
        <int>              <dttm>   <dbl>
1        1105 2016-03-09 00:33:42       8
2        1105 2016-03-09 00:33:43       3
3        1107 2016-03-09 00:44:24      14
4        1107 2016-03-09 00:44:26      14
5        1108 2016-03-09 00:54:02       9
6        1108 2016-03-09 00:54:04      10
7        1109 2016-03-09 01:01:37      17
8        1109 2016-03-09 01:01:39       6
9        1110 2016-03-09 01:02:49      10
10       1110 2016-03-09 01:02:49       8

и setB :

   session_id            datetime request
        <int>              <dttm>   <dbl>
1        1105 2016-03-09 00:33:45       3
2        1107 2016-03-09 00:44:29       7
3        1108 2016-03-09 00:54:06      10
4        1109 2016-03-09 01:01:40       6
5        1110 2016-03-09 01:02:51       5
6        1111 2016-03-09 01:18:36      14
7        1111 2016-03-09 01:18:38      16
8        1112 2016-03-09 01:21:20       1
9        1112 2016-03-09 01:21:21      19
10       1114 2016-03-09 01:29:58      13

И теперь я хочу сделать пересечение на этих двух наборах, но сгруппированных по sessionid

Так как sessionid 1105 в setA содержит запрос (3,7), я хочу сделать пересечение с тем же sessionid, т.е. 1105, содержащий запрос (3) в setB

calc = intersect(setA$request,setB$request) 

... но сгруппированы по sessionid.

Надеюсь, вы поняли.

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Я предлагаю использовать удивительный пакет data.table, потому что для многих задач он быстрее, чем dplyr.

Я немного изменил пример, чтобы было пересечение с длиной> 1.

library(data.table)
A <- data.table("session_id" = c(1105, 1105, 1107 ,1107 ,1108, 1108, 1120),
                "request" = c(8,3,14,15,9,10, 20))
B <- data.table("session_id" = c(1105, 1107, 1107, 1108, 1109, 1110, 1111),
                "request" = c(3, 15, 14, 9, 6, 5, 9))

Сначала мы выполняем внешнее левое соединение, чтобы получить все значения запроса из таблицы B:

C <- merge(A,B, all.x = T, by = "session_id")

Затем мы просто вычисляем длину пересечения с помощью удобной операции «by»и присоедините результат обратно к A:

C[, len_inter := length(intersect(request.x, request.y)), by=session_id]
A[C, len_inter := i.len_inter, on="session_id"]

> A
   session_id request len_inter
1:       1105       8         1
2:       1105       3         1
3:       1107      14         2
4:       1107      15         2
5:       1108       9         1
6:       1108      10         1
7:       1120      20         0

PS: В будущем, пожалуйста, добавьте некоторый код для создания вашего примера data.frames, чтобы людям не приходилось вручную печатать ваши таблицы.

0 голосов
/ 25 апреля 2018

Я думаю, что вы можете сделать это:

library(dplyr)
setA %>% 
  inner_join(setB, by = c("session_id", "request"))

Это приводит к слиянию фрейма данных, где session_id и request одинаковы в обоих наборах данных, отбрасывая datetime.

  session_id request          datetime.x          datetime.y
1       1105       3 2016-03-09 00:33:43 2016-03-09 00:33:45
2       1108      10 2016-03-09 00:54:04 2016-03-09 00:54:06
3       1109       6 2016-03-09 01:01:39 2016-03-09 01:01:40

ОБНОВЛЕНИЕ: Если вы добавите это, вы получите длины пересечений:

setA %>% 
  inner_join(setB, by = c("session_id", "request")) %>% 
  group_by(session_id) %>%
  summarise(lengthintersection = n())

  session_id lengthintersection
   <int>              <int>
1       1105                  1
2       1108                  1
3       1109                  1

ОБНОВЛЕНИЕ: в качестве ответа на комментарий еще одно обновление для расчета пропорций:

setA %>%
  group_by(session_id) %>% 
  mutate(numberrequests = n()) %>% 
  inner_join(setB, by = c("session_id", "request")) %>% 
  summarise(proportion = n()/numberrequests)

# A tibble: 3 x 2
      session_id proportion
        <int>      <dbl>
1       1105        0.5
2       1108        0.5
3       1109        0.5
...