我试图弄清楚如何在一个组中只取出前5行而不用替换另一个变量值。 例如,如果现有数据表(或框架)如下所示:
id V1
1 101
1 102
1 103
1 104
1 105
1 106
1 107
1 108
1 109
1 110
2 101
2 103
2 105
2 107
2 108
2 109
2 110
2 111
2 112
2 101
3 104
3 105
3 107
3 108
3 109
3 110
3 101
3 102
3 103
3 104
但我只想为每个组获得前5行,但不会替换组中的V1值。所以我想要的结果表是......:
id V1
1 101
1 102
1 103
1 104
1 105
2 107
2 108
2 109
2 110
2 111
3 NA
我一直尝试使用for循环,一次遍历每个id。为每个id取前5行,并在前面的id中排除后面的V1值。但是由于我的数据非常大(id的数量超过一百万),for循环需要永远通过所有id。
有没有比我聪明的人能帮助我找到更好,更有效,更聪明的方法来解决这个问题? 非常感谢!
答案 0 :(得分:4)
以下是三个步骤中的选项:
# create a vector to store set values
x <- numeric()
# compute the values by id and update x in the process
res <- lapply(split(df$V1, df$id), function(y) {
y <- head(setdiff(y, x), 5)
x <<- union(x, y)
if(!length(y)) NA else y
})
# combine the result to data.frame
stack(res)
# values ind
#1 101 1
#2 102 1
#3 103 1
#4 104 1
#5 105 1
#6 107 2
#7 108 2
#8 109 2
#9 110 2
#10 111 2
#11 NA 3
答案 1 :(得分:1)
仍在努力。这就是我提出的(请注意,因为id = 3只有重复值,所以最后不会显示)。人们可以改变这一点。我不确定性能。会看看我是否能想出更聪明的东西......
df = data.frame (id = c (1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,
2,2,2,2,2,3,3,3,3,3,3,3,3,3,3),
V1 = c(101,102, 103,104,105,106,107,108,109,110,101,
103,105,107,108,109,110,111,112,101,104,
105,107,108,109,110,101,102,103,104))
df2 <- df
for (i in unique(df$id)) {
dfsel <- data.frame(df2 %>% group_by(id) %>% filter(row_number() <= 5 & id == i))
df3 <- df2[!(df2$V1 %in% dfsel$V1) & df2$id != i,]
df2 <- rbind(dfsel,df3)
}
df2[with (df2, order(id)),]
结果是
id V1
1 101
1 102
1 103
1 104
1 105
2 107
2 108
2 109
2 110
2 111
编辑:找到另一种方式。可能不是真的更聪明,但我玩得很开心:)一个人应该检查性能,没时间考虑它。
这是代码
dd <- split(df$V1, df$id)
maxdf <- data.frame(mx = rep(0,length(dd)))
maxdf[1,1] <- dd[[1]][5]
dd[[1]][dd[[1]] > maxdf[1,1]] <- NA
n <- unique(df$id)[2:length(unique(df$id))]
for (i in n) {
dd[[i]][dd[[i]] <= maxdf[i-1,1]] <- NA
maxdf[i,1] <- dd[[i]][!is.na(dd[[i]])][5]
dd[[i]][dd[[i]] > maxdf[i,1]] <- NA
}
df <- stack(dd)
names(df) <- c("V1","id")
df <- df[!is.na(df$V1),]
PS:下面的解决方案仍然更加优雅:)