Eli*_*nka 32 loops if-statement r apply dataframe
我是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
Run Code Online (Sandbox Code Playgroud)
我需要一个高效的代码,因为我的真实数据帧有大约150000行和200列.这给出了一个错误:
t.d$V4<-t.d$V1[t.d$V1>1]+ t.d$V3[t.d$V3>9]
Run Code Online (Sandbox Code Playgroud)
"申请"是一种选择吗?我试过这个:
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)
Run Code Online (Sandbox Code Playgroud)
但它也会出错.非常感谢您的帮助.
And*_*rie 41
此操作不需要循环,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
Run Code Online (Sandbox Code Playgroud)
为什么这样做?
在第一步中,我创建了一个新列,它是V1和V4列的直接和.我用它within作为一种方便的方式来引用列,d.f而不必一直写d.f$V.
在第二步中,我将所有不满足条件的行分组,并将这些行的V4设置为0.
Nic*_*bbe 25
ifelse 你的朋友在这里:
t.d$V4<-ifelse((t.d$V1>1)&(t.d$V3<9), t.d$V1+ t.d$V3, 0)
Run Code Online (Sandbox Code Playgroud)
Tom*_*mmy 10
我将填写并提供另一个版本.因为如果条件不是mach,你想要零,而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))
Run Code Online (Sandbox Code Playgroud)
......它碰巧比其他解决方案更快;-)
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
Run Code Online (Sandbox Code Playgroud)