【问题标题】:Function to remove certain rows from dataframe函数从dataframe中删除某些行
【发布时间】:2018-06-29 19:01:59
【问题描述】:

我正在尝试编写一个从数据框中删除某些行的函数。 为简单起见,我们假设移除的条件是该行中至少有一个 NA。

    df = data.frame(c("A","B","C"),c(1,NA,3))
fn = function (d) {

  for (x in 1:nrow(d)) { for (y in 1:ncol(d)) {
if(is.na(d[x,y])) d = d[-x,] 
 }}}

fn(df)

PS:我知道有更好的方法来删除至少有一个 NA 的行,即 df = df[-which(!complete.cases(df)] 但我很想知道为什么我写的代码确实如此不工作。

【问题讨论】:

    标签: r function for-loop if-statement na


    【解决方案1】:

    您需要从您的函数中显式返回d

    df <- data.frame(X1 = c("A","B","C"), X2 = c(1,NA,3))
    fn <- function (d) {
      for (x in 1:nrow(d)) {
        for (y in 1:ncol(d)) {
          if(is.na(d[x,y])) d = d[-x,] 
        }
      }
    d # return d
    }
    
    fn(df)
    
    > fn(df)
      X1 X2
    1  A  1
    3  C  3
    

    R 隐式返回最后一次操作的结果,但这是对第三行计算if (...) 的结果,返回NULL

    > foo <- fn(df) # using your fn()
    > foo
    NULL
    

    您可以在函数末尾显式调用return(d),但由于R 也在最后一条语句中调用return(),这就像调用return(return(d))。因此,您只需在函数的最后一行使用d,R 就会做正确的事情。

    不使用return()(即何时应该使用它)的主要例外情况是您可能希望提前从函数中返回。

    最后,与其循环遍历对象的行和列,不如考虑按行工作。 R 是矢量化的,因此您可以在整行上执行 is.na()(例如),然后您的 if() 语句将是 if (any(is.na(d[i, ])) 其中 i 是循环索引,例如:

    fn2 <- function (d) {
      for (i in 1:nrow(d)) {
        if (any(is.na(d[i,]))) {
          d <- d[-i, ]
        }
      }
    d # return d
    }
    
    > fn2(df)
      X1 X2
    1  A  1
    3  C  3
    

    甚至还有更有效的方法可以做到这一点,但如果您以向量化的方式思考,您将开始编写更简单、更快的 R 代码。

    【讨论】:

      【解决方案2】:

      函数式编程风格

      我认为 OP 缺少的是您不能直接修改作为参数传递的变量。这就是函数式编程风格。

      访问https://en.wikipedia.org/wiki/Functional_programming

      事实上,函数体中的变量是作为参数传递的变量的副本。所以你正在制作一个副本。

      这就是为什么您必须返回副本并将其重新分配给变量的原因。

      df <- data.frame(X1 = c("A","B","C"), X2 = c(1,NA,3))
      fn <- function (d) {
              for (x in 1:nrow(d)) {
                for (y in 1:ncol(d)) {
                  if(is.na(d[x,y])) d = d[-x,]}}
               d} # return d
      
      df <- fn(df)
      

      df 现在如 OP 所愿

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-17
        • 2020-12-01
        • 2019-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-14
        • 2020-09-23
        相关资源
        最近更新 更多