从数据框中删除某些行的函数

Function to remove certain rows from dataframe

我正在尝试编写一个从数据框中删除某些行的函数。 为简单起见,让我们假设删除的条件是该行中至少有一个 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)] 但我有兴趣找出为什么我写的代码不起作用。

你需要明确地return 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 隐式 return 是最后一个操作的结果,但这是对第三行 if (...) 求值的结果,returned NULL

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

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

不使用 return() 的主要例外情况(即当您应该使用它时)是在您可能希望 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 代码。

函数式编程风格

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

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

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

这就是为什么您必须 return 复制并将其重新分配给变量的原因。

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 所愿