[英]Summarize a data.table across multiple columns
如何在多列中匯總不可靠數據的data.table ?
具體來說,給定
fields <- c("country","language")
dt <- data.table(user=c(rep(3, 5), rep(4, 5)),
behavior=c(rep(FALSE,5),rep(TRUE,5)),
country=c(rep(1,4),rep(2,6)),
language=c(rep(6,6),rep(5,4)),
event=1:10, key=c("user",fields))
dt
# user behavior country language event
# 1: 3 FALSE 1 6 1
# 2: 3 FALSE 1 6 2
# 3: 3 FALSE 1 6 3
# 4: 3 FALSE 1 6 4
# 5: 3 FALSE 2 6 5
# 6: 4 TRUE 2 5 7
# 7: 4 TRUE 2 5 8
# 8: 4 TRUE 2 5 9
# 9: 4 TRUE 2 5 10
# 10: 4 TRUE 2 6 6
我想得到
# user behavior country.name country.support language.name language.support
# 1: 3 FALSE 1 0.8 6 1.0
# 2: 4 TRUE 2 1.0 5 0.8
(此處x .name
是user
最常用的x , x .support
是觀察到此頂部x的共享事件)
無需像這樣手動通過兩個fields
:
users <- dt[, sum(behavior) > 0, by=user] # have behavior at least once
setnames(users, "V1", "behavior")
dt.out <- dt[, .N, by=list(user,country)
][, list(country[which.max(N)],max(N)/sum(N)), by=user]
setnames(dt.out, c("V1", "V2"), paste0("country",c(".name", ".support")))
users <- users[dt.out]
dt.out <- dt[, .N, by=list(user,language)
][, list(language[which.max(N)], max(N)/sum(N)), by=user]
setnames(dt.out, c("V1", "V2"), paste0("language",c(".name", ".support")))
users <- users[dt.out]
users
# user behavior country.name country.support language.name language.support
# 1: 3 FALSE 1 0.8 6 1.0
# 2: 4 TRUE 2 1.0 5 0.8
實際的fields
數是5,我想避免分別為每個字段重復相同的代碼,如果我修改fields
,則必須編輯此函數。 請注意, 這是這個問題的實質內容,支持計算在別處向我解釋。
與引用的問題一樣 ,我的數據集大約有10 ^ 7行,所以我真的需要一個可擴展的解決方案; 如果我可以像users <- users[dt.out]
那樣避免不必要的復制,那也很好。
這會解決您的問題嗎?
fields <- c("country","language")
dt <- data.table(user=c(rep(3, 5), rep(4, 5)),
behavior=c(rep(FALSE,5),rep(TRUE,5)),
country=c(rep(1,4),rep(2,6)),
language=c(rep(6,6),rep(5,4)),
event=1:10, key=c("user",fields))
CalculateSupport <- function(dt, name) {
x <- dt[, .N, by = eval(paste0('user,', name))]
setnames(x, name, 'name')
x <- x[, list(name[which.max(N)], max(N)/sum(N)), by = user]
setnames(x, c('V1', 'V2'), paste0(name, c(".name", ".support")))
x
}
users <- dt[, sum(behavior) > 0, by=user]
setnames(users, "V1", "behavior")
Reduce(function(x, name) x[CalculateSupport(dt, name)], fields, users)
結果是
user behavior country.name country.support language.name language.support
1: 3 FALSE 1 0.8 6 1.0
2: 4 TRUE 2 1.0 5 0.8
PS請認真對待里卡多對你的問題的評論。 所以有很多很樂意幫助你的人,但是你必須得到很好的尊重。
我無法在一個表達式中執行此操作,因為我不確定如何在data.table表達式中重用已創建的字段。 它也可能不是最有效的方式。 不過,也許這會成為一個很好的起點。
#Find most common country and language for each user
summ.dt<-dt[,list(behavior.summ=sum(behavior)>0,
country.name=dt[user==.BY[[1]],.N,by=country][N==max(N),country],
language.name=dt[user==.BY[[1]],.N,by=language][N==max(N),language]),
by=user]
#Get support for each country and language for each user
summ.dt[,c("country.support","language.support"):=list(
nrow(dt[user==.BY[[1]] & country==country.name])/nrow(dt[user==.BY[[1]]]),
nrow(dt[user==.BY[[1]] & language==language.name])/nrow(dt[user==.BY[[1]]])
),by=user]
user behavior.summ country.name language.name country.support language.support
1: 3 FALSE 1 6 0.8 1.0
2: 4 TRUE 2 5 1.0 0.8
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.