левое соединение и подсчет соответствующего значения для группы R - PullRequest
0 голосов
/ 31 марта 2020

У меня есть два фрейма данных, и я хотел бы знать, сколько у меня совпадающих элементов для каждой группы.

Итак, мой первый df (назовем его df1 ) выглядит так:

Account.ID        Product.ID 
1                 A
1                 B
1                 C
1                 D
1                 E
1                 F
2                 B
2                 D
2                 F
3                 D
3                 E

Мой другой df ( df2 ) содержит информацию для пользователей и продуктов:

User.ID        Product.ID
X              A
X              B
X              C
X              D
X              E
X              F
Y              B
Y              D
Y              G
Z              K
Z              C

Что я хотел бы сделать заключается в подсчете количества Product.ID, которое имеет каждый Account.ID для каждого пользователя. Результат моей мечты будет примерно таким:

Account.ID     User.ID      Percentage_of_Product.ID
1              X            100%
1              Y            66.66%
1              Z            50%
2              X            50%
2              Y            66.66%
2              Z            0%
3              X            33.33%
3              Y            33.33%
3              Z            0%

Проценты, представляющие собой количество Product.ID для каждой учетной записи по отношению к общему количеству Product.ID на пользователя.

Я пробовал много разные вещи, но ничего не работает, поэтому любая помощь будет принята с благодарностью.

Большое спасибо,

Dput: 

df1 <- structure(list(Account.ID = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3
), Product.ID = c("A", "B", "C", "D", "E", "F", "B", "D", "F", 
"D", "E")), row.names = c(NA, -11L), class = c("tbl_df", "tbl", 
"data.frame"))

df2 <- structure(list(User.ID = c("X", "X", "X", "X", "X", "X", "Y", 
"Y", "Y", "Z", "Z"), Product.ID = c("A", "B", "C", "D", "E", 
"F", "B", "D", "G", "K", "C")), row.names = c(NA, -11L), class = c("tbl_df", 
"tbl", "data.frame"))

Ответы [ 2 ]

2 голосов
/ 31 марта 2020

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

left_join(df1, df2, by = "Product.ID") %>%
  group_by(Account.ID, User.ID) %>%
  tally() %>%
  group_by(User.ID) %>%
  mutate(Percentage = 100 * n / sum(n)) %>%
  ungroup()
# # A tibble: 7 x 4
#   Account.ID User.ID     n Percentage
#        <dbl> <chr>   <int>      <dbl>
# 1          1 X           6       54.5
# 2          1 Y           2       40  
# 3          1 Z           1      100  
# 4          2 X           3       27.3
# 5          2 Y           2       40  
# 6          3 X           2       18.2
# 7          3 Y           1       20  
1 голос
/ 31 марта 2020

Я думаю, что использование data.table - это путь к go. Этот код просто уродлив ... но делает то, что вы просили:

df1 <- structure(list(Account.ID = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3
), Product.ID = c("A", "B", "C", "D", "E", "F", "B", "D", "F", 
                  "D", "E")), row.names = c(NA, -11L), class = c("tbl_df", "tbl", 
                                                                 "data.frame"))

df2 <- structure(list(User.ID = c("X", "X", "X", "X", "X", "X", "Y", 
                                  "Y", "Y", "Z", "Z"), Product.ID = c("A", "B", "C", "D", "E", 
                                                                      "F", "B", "D", "G", "K", "C")), row.names = c(NA, -11L), class = c("tbl_df", 
                                                                                                                                         "tbl", "data.frame"))


library(data.table)
# convert your data.frame to data.table
# then it's a matter of rolling joins and group-by.

setDT(df1)
setDT(df2)

product_per_user = df2[ , .N, by = User.ID ]
setkey( df1, Product.ID )
setkey( df2, Product.ID )

matched = df1[ df2 ]
count = na.omit(matched[ , .N, by = .( Account.ID, User.ID ) ])
setorder( count, Account.ID, User.ID )

setkey( count, User.ID )
setkey( product_per_user, User.ID )
final = count[ product_per_user ]
final[ , proportion := 100 * (N / i.N) ]
final[ , `:=` ( N = NULL, i.N = NULL ) ]
setorder( final, Account.ID, User.ID )

> final
   Account.ID User.ID proportion
1:          1       X  100.00000
2:          1       Y   66.66667
3:          1       Z   50.00000
4:          2       X   50.00000
5:          2       Y   66.66667
6:          3       X   33.33333
7:          3       Y   33.33333
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...