33

私はRを初めて使用し、合計する両方の要素が特定の条件を満たす場合、特定のデータフレームの2つの列を合計しようとしています。明確にするために、私がやりたいことは次のとおりです。

> t.d<-as.data.frame(matrix(1:9,ncol=3))
> t.d
  V1 V2 V3
  1  4  7  
  2  5  8  
  3  6  9  

> t.d$V4<-rep(0,nrow(t.d))

> for (i in 1:nrow(t.d)){
+   if (t.d$V1[i]>1 && t.d$V3[i]<9){
+     t.d$V4[i]<-t.d$V1[i]+t.d$V3[i]}
+     }

> t.d    
  V1 V2 V3 V4
  1  4  7  0
  2  5  8 10
  3  6  9  0

実際のデータフレームには約150000行と200列があるため、効率的なコードが必要です。これによりエラーが発生します:

t.d$V4<-t.d$V1[t.d$V1>1]+ t.d$V3[t.d$V3>9] 

「適用」はオプションですか?私はこれを試しました:

t.d<-as.data.frame(matrix(1:9,ncol=3))
t.d$V4<-rep(0,nrow(t.d))

my.fun<-function(x,y){
  if(x>1 && y<9){
    x+y}
}

t.d$V4<-apply(X=t.d,MAR=1,FUN=my.fun,x=t.d$V1,y=t.d$V3)

ただし、エラーも発生します。どうもありがとうございました。

4

3 に答える 3

43

この操作には、ループ、applyステートメント、またはifステートメントは必要ありません。ベクトル化された操作とサブセット化が必要なすべてです。

t.d <- within(t.d, V4 <- V1 + V3)
t.d[!(t.d$V1>1 & t.d$V3<9), "V4"] <- 0
t.d

  V1 V2 V3 V4
1  1  4  7  0
2  2  5  8 10
3  3  6  9  0

なぜこれが機能するのですか?

最初のステップでは、列V1とV4の直接の合計である新しい列を作成します。いつも書くことなくwithin、の列を参照する便利な方法として使用します。d.fd.f$V

2番目のステップでは、条件を満たさないすべての行をサブセット化し、これらのV4を0に設定します。

于 2011-06-29T09:48:52.627 に答える
25

ifelseここにあなたの友達がいます:

t.d$V4<-ifelse((t.d$V1>1)&(t.d$V3<9), t.d$V1+ t.d$V3, 0)
于 2011-06-29T09:49:39.657 に答える
10

チップインして、さらに別のバージョンを提供します。条件がうまくいかない場合はゼロが必要であり、TRUE / FALSEは1/0の栄光のバージョンであるため、条件を掛けるだけでも機能します。

t.d<-as.data.frame(matrix(1:9,ncol=3))
t.d <- within(t.d, V4 <- (V1+V3)*(V1>1 & V3<9))

...そしてそれはたまたま他の解決策よりも速いです;-)

t.d <- data.frame(V1=runif(2e7, 1, 2), V2=1:2e7, V3=runif(2e7, 5, 10))
system.time( within(t.d, V4 <- (V1+V3)*(V1>1 & V3<9)) )         # 3.06 seconds
system.time( ifelse((t.d$V1>1)&(t.d$V3<9), t.d$V1+ t.d$V3, 0) ) # 5.08 seconds
system.time( { t.d <- within(t.d, V4 <- V1 + V3); 
               t.d[!(t.d$V1>1 & t.d$V3<9), "V4"] <- 0 } )       # 4.50 seconds
于 2011-06-29T20:21:28.443 に答える