【问题标题】:how to create function with input from dataframe and apply it over all rows?如何使用来自数据框的输入创建函数并将其应用于所有行?
【发布时间】:2021-06-29 10:41:23
【问题描述】:

我尝试在 R 中编写一个函数,该函数将数据帧中的多个变量作为输入,并给出一个带有结果的向量作为输出。

根据下面的这篇文章,我确实编写了下面的函数。 How can create a function using variables in a dataframe

虽然我收到了这条警告信息:

the condition has length > 1 and only the first element will be used

我试图通过下面的帖子在函数中使用 sapply 来解决它,尽管我没有成功。 https://datascience.stackexchange.com/questions/33351/what-is-the-problem-with-the-condition-has-length-1-and-only-the-first-elemen

# a data frame with columns a, x, y and z:

myData <- data.frame(a=1:5,
                     x=(2:6),
                     y=(11:15),
                     z=3:7)


myFun3 <- function(df, col1 = "x", col2 = "y", col3 = "z"){      
   result <- 0      
   if(df[,col1] == 2){result <- result + 10
   }      
   if(df[,col2] == 11){result <- result + 100
   }      
   return(result)
}

myFun3(myData)

>    Warning messages:
>    1: In if (df[, col1] == 2) { :
>      the condition has length > 1 and only the first element will be used
>    2: In if (df[, col2] == 11) { :
>      the condition has length > 1 and only the first element will be used

谁能解释我如何将函数应用于数据框的所有行? 非常感谢!

【问题讨论】:

    标签: r function dataframe sapply


    【解决方案1】:

    我们需要ifelse 而不是if/else,因为if/else 没有矢量化

    myFun3 <- function(df, col1 = "x", col2 = "y", col3 = "z"){ 
           result <- numeric(nrow(df))
           ifelse(df[[col1]] == 2,  result + 10,
               ifelse(df[[col2]] == 11, result + 100, result))     
    
       }
    
    myFun3(myData)
    #[1] 10  0  0  0  0
    

    或者在进行一些更改后,OP 的代码可以是Vectorized,即使用else if 阶梯删除第二个if

    myFun3 <- Vectorize(function(x, y){      
       result <- 0      
       if(x == 2) {
           result <- result + 10
        } else if(y == 11){
           result <- result + 100
         } else result <- 0     
       return(result)
    })
    myFun3(myData$x, myData$y)
    #[1] 10  0  0  0  0
    

    关于 OP 对多个条件何时为 TRUE 的疑问,然后只希望第一个被执行,ifelse(嵌套 - 如果两个以上)或if/else if/elseelse if 阶梯或 if/else 嵌套)两者都有效,因为它以我们指定条件的相同顺序执行,并且一旦发生 TRUE 条件即停止,即假设我们有多个条件

     if(expr1) {
        1
     } else if(expr2) {
        2
     } else if(expr3) {
       3
     } else if(expr4) {
       4
     } else {
       5}
    

    首先检查第一个表达式 ('expr1'),然后是第二个,依此类推。当它返回 TRUE 时,它就退出,即它是一个嵌套条件

    if(expr1) {
         1
      } else {
            if(expr2) {
              2
             } else {
                 if(expr3) {
                   3
                  } else {
                     if(expr4) {
                      4
                      } else 5
                        }
                     }
               }
    

    这是有代价的,即只要我们有更多与 1 匹配的值,就只执行 expr1 从而节省时间,但如果有超过 5 个值,则检查所有这些条件

    【讨论】:

    • @akrun 谢谢!尽管在我的函数中,这两个条件都可以成立。这可能导致结果 100 + 10 = 110。我应该让示例有所不同。我已将 if(df[,col2] == 3) 更改为 if(df[,col2] == 11) 以使其更好地可见。
    • @user2165379 所以,ifelse 的第一个代码仍然有效,对吧?
    • @akrun 是的。我应该先自己进一步尝试。我想我需要一个矢量化的 if。
    • @user2165379 向量化的 if/else 是 ifelse
    • @akrun 似乎向量化的“如果”不存在?如果我理解正确,只有矢量化 if/else。你是什​​么意思第一个代码仍然适用于“ifelse”?如果两个条件都为真,它就不起作用。
    猜你喜欢
    • 2019-04-20
    • 2018-08-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 2021-11-08
    • 2019-09-09
    • 1970-01-01
    • 2012-06-03
    相关资源
    最近更新 更多