[英]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.