Spencer K
Spencer K

Reputation: 73

non-numeric argument to binary operator with ifelse and apply

I hope nobody is getting (too) tired of me. I have given a completely fictional example of the problem below. The error is only given after including a mixture of numeric and string column in a data frame, even if the numeric columns are excluded from the function (not shown below). The function looks in column c for contents of d and vice-versa using grepl and then the should make a new column of the 'yes' and 'no' statements from ifelse. I need to ifelse to return the 'yes' and 'no' after the test but this is the part that is giving the error.

  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

Upvotes: 2

Views: 358

Answers (2)

dcarlson
dcarlson

Reputation: 11046

You can also vectorize grepl to simplify your code:

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

Upvotes: 0

Kozolovska
Kozolovska

Reputation: 1119

Into the question. The best way to approach the question is using the function case_when from the package dplyr. I used the function str_detect from stringr.

> 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

The error is caused since you use apply which forces the matrix to a character matrix (transforming the numeric values to character). Example,

> 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"

Some pointers as it seems that you are new to R. First of all, do not use c as a name it is very commonly used function to combine elements to a vector. Second, the way the function is written is very hard to read. You should break it up into multiple step to make it easier.

Upvotes: 1

Related Questions