Max*_*den 6 indexing split r plyr data.table
我正在努力完成以下工作:
示例数据集:
belongID uniqID Time Rating
1 101 5 0
1 102 4 0
2 103 4 0
2 104 3 0
2 105 2 5
3 106 4 2
3 107 5 0
3 108 5 1
Run Code Online (Sandbox Code Playgroud)
问题是:我想提取每个belongsID的最新条目(时间的最大值),除非此评级为0.如果最近条目的评级为0.我希望第一个条目具有评级(不是最高评级,只是第一个评级不为零的值).如果所有其他条目也为零,则需要选择最新的条目.
最终结果应该是:
belongID uniqID Time Rating
1 101 5 0
2 105 2 5
3 108 5 1
Run Code Online (Sandbox Code Playgroud)
数据集非常大,按belongsID排序.它不是按时间排序的,因此更新的条目可能会在具有相同belongsID的旧条目之后出现.
如果没有"0 Rating"约束,我使用以下函数来计算最近的条目:
>uniqueMax <- function(m, belongID = 1, time = 3) {
t(
vapply(
split(1:nrow(m), m[,belongID]),
function(i, x, time) x[i, , drop=FALSE][which.max(x[i,time]),], m[1,], x=m, time=time
)
)
}
Run Code Online (Sandbox Code Playgroud)
我不知道如何纳入"0评级"约束.
编辑:后续问题:
有没有人知道getRating
如果不仅评估零,应该如何改变功能,但需要考虑更多的评级(例如0,1,4和5)?因此,除非评级为0或1或4或5,否则分配给最近的?如果评级为0,1,4,5,则分配给具有不同评级的最近一个条目.如果所有等级都是0,1,4或5分配给最近的那些.我尝试了以下,但这不起作用:
getRating <- function(x){
iszero <- x$Rating == 0 | x$Rating == 1 | x$Rating == 4 | x$Rating ==5
if(all(iszero)){
id <- which.max(x$Time)
} else {
id <- which.max((!iszero)*x$Time)
# This trick guarantees taking 0 into account
}
x[id,]
}
# Do this over the complete data frame
do.call(rbind,lapply(split(Data,Data$belongID),getRating))
# edited per Tyler's suggestion'
Run Code Online (Sandbox Code Playgroud)
这是一个使用 data.table 的解决方案,可以轻松过滤并getRecentRow
为每个 单独执行我的功能belongID
。
library(data.table)
# Load the data from the example.
dat = structure(list(belongID = c(1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L),
uniqID = 101:108, Time = c(5L, 4L, 4L, 3L, 2L, 4L, 5L, 5L),
Rating = c(0L, 0L, 0L, 0L, 5L, 2L, 0L, 1L)),
.Names = c("belongID", "uniqID", "Time", "Rating"),
row.names = c(NA, -8L), class = c("data.table", "data.frame"))
dat = data.table(dat) # Convert to data table.
# Function to get the row for a given belongID
getRecentRow <- function(data) {
# Filter by Rating, then order by time, then select first.
row = data[Rating != 0][order(-Time)][1]
if(!is.na(row$uniqID)) {
# A row was found with Rating != 0, return it.
return(row)
} else {
# The row was blank, so filter again without restricting. rating.
return(data[order(-Time)][1])
}
}
# Run getRecentRow on each chunk of dat with a given belongID
result = dat[,getRecentRow(.SD), by=belongID]
belongID uniqID Time Rating
[1,] 1 101 5 0
[2,] 2 105 2 5
[3,] 3 108 5 1
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
179 次 |
最近记录: |