簡體   English   中英

左連接並計算每個組 R 的匹配值

[英]left join and count matching value per group R

我有兩個數據框,我想知道每個組從一個到另一個有多少匹配項。

所以我的第一個 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

我想要做的是計算每個 Account.IDs 相對於每個用戶的 Product.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"))

我認為這就是你想要的,使用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  

我認為使用data.table是要走的路。 這段代碼很丑……但是按照您的要求執行:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM