【问题标题】:Loop over rows of dataframe applying function with if-statement使用 if 语句循环应用函数的数据帧行
【发布时间】:2011-09-24 23:55: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)

但它也给出了一个错误。 非常感谢您的帮助。

【问题讨论】:

  • +1 用于创建示例数据和您自己的代码尝试。
  • 欢迎来到 SO。这是一个很好的问题的一个很好的例子。

标签: r loops if-statement dataframe apply


【解决方案1】:

我会加入并提供另一个版本。如果条件不匹配,您希望为零,并且 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

【讨论】:

    【解决方案2】:

    ifelse 是你的朋友:

    t.d$V4<-ifelse((t.d$V1>1)&(t.d$V3<9), t.d$V1+ t.d$V3, 0)
    

    【讨论】:

      【解决方案3】:

      此操作不需要循环、应用语句或 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.f 的列,而不必一直写d.f$V。

      在第二步中,我对所有不满足条件的行进行子集化,并将这些行的 V4 设置为 0。

      【讨论】:

      • 谢谢!如此简单而完美。我不敢相信我花了半天时间思考这个问题。
      • 如果它能让你感觉更好,那么当我开始使用 R 时,这类问题会让我头晕目眩。:-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 1970-01-01
      相关资源
      最近更新 更多