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)
ただし、エラーも発生します。ご協力ありがとうございます。
この操作は、ループ、適用ステートメント、または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列の直線和である新しい列を作成します。 d.f
を常に記述する必要なく、d.f$V
の列を参照する便利な方法としてwithin
を使用します。
2番目のステップでは、条件を満たさないすべての行をサブセット化し、これらのV4を0に設定します。
ifelse
はあなたの友達です:
t.d$V4<-ifelse((t.d$V1>1)&(t.d$V3<9), t.d$V1+ t.d$V3, 0)
チップインして、さらに別のバージョンを提供します。条件が一致しない場合はゼロが必要であり、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