R在数据帧中的顺序行上起作用

时间:2013-03-04 22:35:28

标签: r dataframe

我有一个由大多数连续行组成的数据框。大多数意味着有些是不按顺序或丢失。当存在当前行的顺序行时,我想使用来自两行的数据执行某些功能。如果它不存在,请跳过它然后继续。我知道我可以通过循环来做到这一点,但它很慢。我认为这与使用索引有关。以下是使用示例数据和使用循环的所需结果的问题示例。

df <- data.frame(id=1:10, x=rnorm(10))
df <- df[c(1:3, 5:10), ]
df$z <- NA


dfLoop <- function(d)
{
  for(i in 1:(nrow(d)-1))
  {
    if(d[i+1, ]$id - d[i, ]$id == 1)
    {
      d[i, ]$z = d[i+1, ]$x - d[i, ]$x
    }
  }

  return(d)
}

dfLoop(df)

那么如何在不使用循环的情况下获得相同的结果呢?谢谢你的帮助。

4 个答案:

答案 0 :(得分:3)

尝试一下:

index <- which(diff(df$id)==1) #gives the index of rows that have a row below in sequence

df$z[index] <- diff(df$x)[index]

作为一项功能:

fun <- function(x) {
  index <- which(diff(x$id)==1)
  xdiff <- diff(x$x)
  x$z[index] <- xdiff[index]
  return(x)
}

与你的循环比较:

a <- fun(df)
b <- dfLoop(df)
identical(a, b)
[1] TRUE

答案 1 :(得分:1)

R是基于矢量的。试试这段代码 - 它就像你的for循环,但一次使用整个范围:

i <- 1:(nrow(d)-1)
d[i+1, ]$id - d[i, ]$id == 1

您应该看到一个长度为nrow(d) - 1的向量,其中包含条件所在的索引。保存它:

cond <- (d[i+1, ]$id - d[i, ]$id == 1)

您还可以获取所有TRUE值的位置:

(cond.pos <- which(cond))

现在,您可以为条件为true的索引分配值:

d[cond.pos, ]$z <- d[cond.pos+1, ]$x - d[cond.pos, ]$x

有很多方法可以达到你想要的效果,但要获得“基于矢量”的想法需要一些经验。特别是alexwhan所指出的diff函数可以帮助保存这个特定示例的一些输入。

答案 2 :(得分:0)

不是最漂亮的,但它会在没有循环的情况下运行:

> df <- data.frame(id=1:10, x=rnorm(10))
> df <- df[c(1:3, 5:10), ]
> df$z <- NA
> df
   id           x  z
1   1 -1.91564886 NA
2   2  0.27260879 NA
3   3 -1.08563119 NA
5   5 -0.13747215 NA
6   6 -0.38367874 NA
7   7 -1.17825737 NA
8   8 -0.08521386 NA
9   9 -0.44392382 NA
10 10 -0.97192253 NA
> 
> temp = c(df$id,1:10)
> temp
 [1]  1  2  3  5  6  7  8  9 10  1  2  3  4  5  6  7  8  9 10
> 
> idx = which(table(temp)<2)
> idx 
4 
4 
> 
> newdf = df[-idx,]
> newdf
   id           x  z
1   1 -1.91564886 NA
2   2  0.27260879 NA
3   3 -1.08563119 NA
6   6 -0.38367874 NA
7   7 -1.17825737 NA
8   8 -0.08521386 NA
9   9 -0.44392382 NA
10 10 -0.97192253 NA
> 
> newdf$z = newdf$x[2:nrow(df)] - newdf$x[1:(nrow(df)-1)]
> newdf
   id           x          z
1   1 -1.91564886  2.1882577
2   2  0.27260879 -1.3582400
3   3 -1.08563119  0.7019524
6   6 -0.38367874 -0.7945786
7   7 -1.17825737  1.0930435
8   8 -0.08521386 -0.3587100
9   9 -0.44392382 -0.5279987
10 10 -0.97192253         NA
> 
> newdf = rbind(newdf,df[idx,])
> newdf
   id           x          z
1   1 -1.91564886  2.1882577
2   2  0.27260879 -1.3582400
3   3 -1.08563119  0.7019524
6   6 -0.38367874 -0.7945786
7   7 -1.17825737  1.0930435
8   8 -0.08521386 -0.3587100
9   9 -0.44392382 -0.5279987
10 10 -0.97192253         NA
5   5 -0.13747215         NA
> 
> newdf = newdf[order(newdf$id),]
> newdf
   id           x          z
1   1 -1.91564886  2.1882577
2   2  0.27260879 -1.3582400
3   3 -1.08563119  0.7019524
5   5 -0.13747215         NA
6   6 -0.38367874 -0.7945786
7   7 -1.17825737  1.0930435
8   8 -0.08521386 -0.3587100
9   9 -0.44392382 -0.5279987
10 10 -0.97192253         NA

答案 3 :(得分:0)

首先计算所有&#34;第一个差异&#34;然后将非连续行设置为NA:

 df[1:(nrow(df)-1), "z"] <- df[-1, "x"] - df[-nrow(df), "x"]
 is.na(df[-nrow(df), "z"]) <- diff( df$id) !=1
 df
#
   id           x           z
1   1 -0.04493361  0.02874335
2   2 -0.01619026  0.96002647
3   3  0.94383621          NA
5   5  0.59390132  0.32507605
6   6  0.91897737 -0.13684107
7   7  0.78213630 -0.70757132
8   8  0.07456498 -2.06391668
9   9 -1.98935170  2.60917744
10 10  0.61982575          NA

负数索引在创建稍短版本的矢量时很有用。 is.na<-函数在其RHS上采用逻辑参数,并使用它将其LHS侧目标中的所有条目设置为NA,以符合&#34;判定&#34;逻辑向量。