向下移动一行,一次删除最后一行n行

时间:2017-06-16 11:47:02

标签: r shift

我已经阅读了shift和seq的说明,但我自己无法想出这个。 我需要向下移动一列数字,一次3行,消除最后一个值。 如果我有:

 serial  val1
    1      6
    2      8
    3      7
    4      11
    5      9 
    6      3

我需要的输出是:

 serial val1   val2
  1       6      NULL
  2       8      6
  3       7      8
  4       11     NULL
  5       9      11 
  6       3      9

我有大约300k行。

3 个答案:

答案 0 :(得分:2)

使用data.table中的set,您可以消除每第3行:

test <- data.table(serial = c(1, 2, 3, 4, 5, 6, 7), val1 = c(6, 8, 7, 11, 9, 3, 4))
test[, val2 := shift(val1)]
for (i in seq(1, nrow(test), 3)){
    set(test, i = i, j = 3, value = NA)
}

   serial val1 val2
1:      1    6   NA
2:      2    8    6
3:      3    7    8
4:      4   11   NA
5:      5    9   11
6:      6    3    9
7:      7    4   NA

答案 1 :(得分:2)

这是另一种解决方案(使用gl()):

library("data.table")
df <- data.table(serial = c(1, 2, 3, 4, 5, 6, 7), val1 = c(6, 8, 7, 11, 9, 3, 4))
n <- df[, .N]
df[, f:=gl(n, 3, length=n)]
df[, val2 := shift(val1), by = f]
# > df
#    serial val1 f val2
# 1:      1    6 1   NA
# 2:      2    8 1    6
# 3:      3    7 1    8
# 4:      4   11 2   NA
# 5:      5    9 2   11
# 6:      6    3 2    9
# 7:      7    4 3   NA

答案 2 :(得分:0)

基础R

d1 = data.frame(serial=1:6, val1=c(6,8,7,11,9,3))

#' Return new vector with values of each len in v shifted one index
#' It is an error if v modulo len is =! 0
shiftnew = function(v, len, simpl=T) {
  stopifnot(length(v) %% len == 0) 
  ind = as.factor(rep(1:(length(v)/len), each=len))
  newv <- tapply(v, ind, function(chunk){

    shifted <- c(NA, chunk[1:(len-1)])
  })
  if(simpl) unlist(newv)

}

d1$val2 <- shiftnew(d1[, "val1"], 3)

#output
  serial val1 val2
1      1    6   NA
2      2    8    6
3      3    7    8
4      4   11   NA
5      5    9   11
6      6    3    9