我有一个由大多数连续行组成的数据框。大多数意味着有些是不按顺序或丢失。当存在当前行的顺序行时,我想使用来自两行的数据执行某些功能。如果它不存在,请跳过它然后继续。我知道我可以通过循环来做到这一点,但它很慢。我认为这与使用索引有关。以下是使用示例数据和使用循环的所需结果的问题示例。
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)
那么如何在不使用循环的情况下获得相同的结果呢?谢谢你的帮助。
答案 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;逻辑向量。