Сопоставить данные группы с данными пользователя и получить группы - PullRequest
0 голосов
/ 26 сентября 2018

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

User Product
A .   1
A .   2
A .   3
B .   1
B .   3
B .   4

И еще одна таблица

Group Product
X1 .   1
X1 .   2
X1 .   4
X2 .   1
X2 .   3

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

User X1 X2
A .   1  0
B .   0 .1

Я пытался вручную делать циклы, пытался сопоставить функции настройки, но мой фактический размер данных довольно велик, а решения не идеальны.

Нужна помощь в этом.

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

Другой ответ, который использует только dplyr и цикл будет:

library(dplyr)
myFunction = function(df1, df2, user, group, product){
  user = deparse(substitute(user))
  product = deparse(substitute(product))
  group = deparse(substitute(group))
  answer = data.frame(User = as.character(df1[1, user]))
  for(i in unique(df2[,group])){
    temp = df1 %>% summarise(!!i := if_else(all(df2[which(df2[,group] == i),][,product] %in% unique(df1[[product]])), 1, 0))
    answer = cbind(answer, temp[,i])
  }
  return(answer)
}

df1 %>% group_by(User) %>% do(myFunction(., df2, User, Group, Product))
df1

# A tibble: 2 x 3
# Groups:   User [2]
  User     X1    X2
  <chr> <dbl> <dbl>
1 1         0     1
2 2         0     1
0 голосов
/ 26 сентября 2018

Вот решение, использующее только dplyr и tidyr -

library(dplyr)
library(tidyr)

user_product <- data.frame(User = rep(LETTERS[1:2], each = 3), Product = c(1:3, 1, 3, 4))
group_product <- data.frame(Group = c("x1", "x1", "x1", "x2", "x2"), Product = c(1,2,4,1,3))

left_join(user_product, group_product, by = "Product") %>%
  left_join(group_product, by = "Group") %>%
  group_by(User, Group) %>%
  summarize(
    test = all(Product.y %in% Product.x)
  ) %>%
  spread(Group, test)

# A tibble: 2 x 3
# Groups:   User [2]
  User  x1    x2   
  <fct> <lgl> <lgl>
1 A     FALSE TRUE 
2 B     FALSE TRUE

Несколько похоже на то, что уже используется @ r2evans, но гораздо менее многословно, проще для понимания и на одну зависимость меньше пакета.

0 голосов
/ 26 сентября 2018

Вы можете сделать это с помощью некоторого аккуратного кода.

Во-первых, некоторые данные без точек (я решил, что точки не нужны, исправьте меня, если я ошибаюсь):

x1 <- read.table(header=TRUE, stringsAsFactors=FALSE, text='
User Product
A    1
A    2
A    3
B    1
B    3
B    4')
x2 <- read.table(header=TRUE, stringsAsFactors=FALSE, text='
Group Product
X1    1
X1    2
X1    4
X2    1
X2    3')
out <- read.table(header=TRUE, stringsAsFactors=FALSE, text='
User X1 X2
A    1  0
B    0  1')

Необходимые пакеты:

library(dplyr)
library(tidyr)
library(purrr)

x1n <- group_by(x1, User) %>% nest(.key = "x1prod")
x2n <- group_by(x2, Group) %>% nest(.key = "x2prod")

crossing(User = x1n$User, Group = x2n$Group) %>%
  left_join(x1n, by = "User") %>%
  left_join(x2n, by = "Group") %>%
  mutate(allx = map2_lgl(x1prod, x2prod, ~ all(.y$Product %in% .x$Product)))
# # A tibble: 4 x 5
#   User  Group x1prod           x2prod           allx 
#   <chr> <chr> <list>           <list>           <lgl>
# 1 A     X1    <tibble [3 x 1]> <tibble [3 x 1]> FALSE
# 2 A     X2    <tibble [3 x 1]> <tibble [2 x 1]> TRUE 
# 3 B     X1    <tibble [3 x 1]> <tibble [3 x 1]> FALSE
# 4 B     X2    <tibble [3 x 1]> <tibble [2 x 1]> TRUE 

Это, конечно, не ваш желаемый результат, но я показываю этот вывод, чтобы продемонстрировать, что делает вложение и что мы сравниваем по строкам x1prod (один столбецProduct) и x2prod (то же самое).Отсюда достаточно простого удаления столбцов и расширения:

crossing(User = x1n$User, Group = x2n$Group) %>%
  left_join(x1n, by = "User") %>%
  left_join(x2n, by = "Group") %>%
  mutate(allx = map2_lgl(x1prod, x2prod, ~ all(.y$Product %in% .x$Product))) %>%
  select(-x1prod, -x2prod) %>%
  spread(Group, allx)
# # A tibble: 2 x 3
#   User  X1    X2   
#   <chr> <lgl> <lgl>
# 1 A     FALSE TRUE 
# 2 B     FALSE TRUE 

(я также предполагаю, что желаемый результат немного ошибочен, так как A не имеет «4» из группы X1.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...