3

ほとんどが連続した行で構成されているデータフレームがあります。主に、一部が順序どおりでないか欠落していることを意味します。現在の行の連続行が存在する場合、両方の行のデータを使用していくつかの機能を実行したいと思います。存在しない場合は、スキップして次に進みます。私はループでこれを行うことができることを知っていますが、それはかなり遅いです。これはインデックスの使用と関係があると思います。これは、サンプルデータを使用した問題の例と、ループを使用した望ましい結果です。

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

4 に答える 4

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
于 2013-03-04T22:44:05.740 に答える
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))

これで、条件が真であるインデックスに値を割り当てることができます。

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

あなたが望むものを達成するためのかなりの数の方法がありますが、「ベクトルベース」のアイデアをつかむにはある程度の経験が必要です。特に、diffalexwhanが指摘しているように、この関数は、この特定の例の入力を節約するのに役立ちます。

于 2013-03-04T22:58:24.143 に答える
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
于 2013-03-04T22:52:02.100 に答える
0

これは最初にすべての「最初の差」を計算し、次に非連続行を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として設定します。

于 2013-03-05T01:36:04.933 に答える