【问题标题】:Logical operators and strings: function error逻辑运算符和字符串:函数错误
【发布时间】:2020-02-18 18:07:16
【问题描述】:

这是一个产生错误的最小可重现示例:

 comb3 <- function(x) {
      if (x == "Unable to do") {
        x = 0
      } 
    } 

这是我原来的功能:

 comb <- function(x) {
      if (x == "Unable to do") {
        x = 0
      } else if (x == "Very difficult to do") {
        x = 1
      } else if (x == "Somewhat difficult to do") {
        x = 2
      } else if (x == "Not difficult") {
        x = 3
      } 
    }

我正在尝试在下面采样的列上使用此功能。我收到此错误:

Warning messages:
1: In if (x == "Unable to do") { :
  the condition has length > 1 and only the first element will be used
2: In if (x == "Very difficult to do") { :
  the condition has length > 1 and only the first element will be used

Here is a sample of what the data in one column looks like:
sample <- c("Unable to do", "Somewhat difficult to do", "Very difficult to do", "Unable to do", "Not difficult","Unable to do","Very difficult to do", "Not difficult", "Unable to do", "Not difficult")        

【问题讨论】:

  • 那么,您想根据列名修改列吗?
  • 如果您使用的是mutate_at,您似乎需要case_when。但是您也应该显示您的dplyr 代码并包含一些示例数据以制作正确的reproducible example
  • 在未使用 dplyr 函数的情况下对单个列执行函数(列)时出现错误,这就是我没有包含它的原因。我还没有尝试将此功能与 dplyr 一起使用。 @MrFlick
  • @slava-kohut 实际上我提供的样本是一列。让我澄清一下。
  • @Krishna if() 不是矢量化控制流语句。如果我有x&lt;-c(3,10) 而我有if(x&gt;5) print("ok"),这将不起作用,因为x 有两个值,其中一些值小于5 和一些更大。在这种情况下,一条if 语句不起作用。您需要ifelse()if_elsecase_when,因为函数一次对data.frame 的所有行进行操作。

标签: r function logical-operators data-cleaning


【解决方案1】:

警告消息很好地描述了您的代码存在的问题。 if 是一个函数,它期望长度为一个逻辑向量作为输入。因此,要在向量上使用条件,您应该改用 ifelse 之类的东西,或者如 MrFlick 所说,使用 case_whenmutate_at

使用ifelse 的函数的等效版本是这样的:

comb1 <- function(x) {
  ifelse(x == "Unable to do", 
    0,
    ifelse (x == "Very difficult to do",
      1,
      ifelse(x == "Somewhat difficult to do",
        2,
        ifelse(x == "Not difficult",
          3,
          ## If not match then NA
          NA
        )
      )
    )
  )
}

请注意,这很难阅读,因为 ifelse 调用被链接在一起。 因此,您可以通过在调用 sapply 时使用稍微修改过的函数版本来完成同样的事情来避免这种情况

comb2 <- function(x) {
  sapply(x, function(y) {
    if (y == "Unable to do") {
      0
    } else if (y == "Very difficult to do") {
      1
    } else if (y == "Somewhat difficult to do") {
      2
    } else if (y == "Not difficult") {
       3
    }
  ## USE.NAMES = FALSE means that the output is not named, and has no other effect
  }, USE.NAMES = FALSE)
}

您还可以使用因子,它们在内部编码为从 1 开始的整数,并且 (ab) 使用它从字符串转换为数字:

comb3 <- function(x) {
  fac <- factor(x, 
    levels = c(
      "Unable to do",
      "Very difficult to do",
      "Somewhat difficult to do",
      "Not difficult"
    )
  )
  as.numeric(fac) - 1
}

这 3 个版本的输出是相同的,并且是一个很好的例子,说明了在 R 中可以有多种方法来完成任务。这有时可能是一种诅咒而不是一种恩赐。

sample <- c("Unable to do", "Somewhat difficult to do", "Very difficult to do", "Unable to do", "Not difficult","Unable to do","Very difficult to do", "Not difficult", "Unable to do", "Not difficult")
comb1(sample)
# [1] 0 2 1 0 3 0 1 3 0 3
comb2(sample)
# [1] 0 2 1 0 3 0 1 3 0 3
comb3(sample)
# [1] 0 2 1 0 3 0 1 3 0 3

【讨论】:

  • 感谢您详细解答aocall并演示每个选项的结果。我会研究他们的实施!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-13
  • 1970-01-01
相关资源
最近更新 更多