r-如何在没有替换的另一个变量值中乘以前5行



我试图弄清楚如何仅在另一个变量值中替换一个组仅乘以前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

我一直在尝试通过一次浏览每个ID的循环来做到这一点。...对每个ID进行前5行,并排除以下ID中具有V1值的以下行。但是,由于我的数据确实很大(ID的数量超过一百万(,因此For Loop永远需要所有ID。

是否有人比我更聪明,可以帮助我找到一种更好,更高效,更聪明的解决这个问题的方法?非常感谢!

这是三个步骤的选项:

# 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

仍在处理它。这就是我想到的(请注意,由于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:下面的解决方案仍然更加优雅:(

最新更新