【问题标题】:non-numeric argument to binary operator with ifelse and apply带有 ifelse 和 apply 的二元运算符的非数字参数
【发布时间】:2021-10-07 02:03:35
【问题描述】:

我希望没有人会(太)厌倦我。我在下面给出了一个完全虚构的问题示例。仅在数据框中包含数字和字符串列的混合后才会给出错误,即使从函数中排除了数字列(下面未显示)。该函数使用 grepl 在 c 列中查找 d 的内容,反之亦然,然后应该从 ifelse 中创建一个包含“yes”和“no”语句的新列。我需要在测试后返回“是”和“否”,但这是给出错误的部分。

  a <- c(5:10)
  b <- c(105:110)
  c <- c("a","b","c","d","e","f")
  d <- c("aa","bc","cd","ff","ee", "gf")
  df <- data.frame(a,b,c,d)

  newfunction <- function(x, col1, col2, col3, col4){ifelse(((sapply(lapply(x[[col4]], grepl, 
  x[[col3]]),any)) | (sapply(lapply(x[[col3]], grepl, x[[col4]]),any))), (11 - x[[col1]]), (1 - 
  x[[col2]]))}
  df$new <- apply(df, 1, newfunction, "a", "b", "c", "d")
  
  Error in 11 - x[[col1]] : non-numeric argument to binary operator

【问题讨论】:

    标签: r if-statement apply


    【解决方案1】:

    进入问题。解决这个问题的最佳方法是使用包dplyr 中的函数case_when。我使用了来自stringr 的函数str_detect

    > library(tidyverse)
    > library(stringr)
    > 
    > a  <- c(5:10)
    > b  <- c(105:110)
    > cc <- c("a","b","c","d","e","f")
    > d  <- c("aa","bc","cd","ff","ee", "gf")
    > df <- data.frame(a, b, cc, d)
    > 
    > 
    > 
    > df %>% mutate(case_when((str_detect(cc, d) | str_detect(d, cc)) ~ 'Yes', 
    +                         TRUE ~ 'No'))
       a   b cc  d case_when(...)
    1  5 105  a aa            Yes
    2  6 106  b bc            Yes
    3  7 107  c cd            Yes
    4  8 108  d ff             No
    5  9 109  e ee            Yes
    6 10 110  f gf            Yes
    

    错误是因为您使用apply 将矩阵强制为字符矩阵(将数值转换为字符)引起的。例如,

    > apply(df, 2, function(x) x)
         a    b     cc  d   
    [1,] " 5" "105" "a" "aa"
    [2,] " 6" "106" "b" "bc"
    [3,] " 7" "107" "c" "cd"
    [4,] " 8" "108" "d" "ff"
    [5,] " 9" "109" "e" "ee"
    [6,] "10" "110" "f" "gf"
    

    一些指针,因为您似乎是 R 新手。首先,不要使用 c 作为名称,它是非常常用的函数,用于将元素组合到向量。 其次,函数的编写方式非常难以阅读。您应该将其分解为多个步骤以使其更容易。

    【讨论】:

      【解决方案2】:

      您还可以对grepl 进行矢量化以简化您的代码:

      Vgrepl <- Vectorize(grepl)
      TF <- Vgrepl(pattern=df$c, x=df$d) | Vgrepl(pattern=df$d, x=df$c)
      df$comp <- ifelse(TF, "Yes", "No")
      df
      #    a   b c  d comp
      # 1  5 105 a aa  Yes
      # 2  6 106 b bc  Yes
      # 3  7 107 c cd  Yes
      # 4  8 108 d ff   No
      # 5  9 109 e ee  Yes
      # 6 10 110 f gf  Yes
      

      【讨论】:

        猜你喜欢
        • 2018-08-24
        • 1970-01-01
        • 1970-01-01
        • 2021-03-24
        • 2016-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多