AlSub
AlSub

Reputation: 1155

Failing to replace typo for NA for a list in R

I would like to replace this typo "-" for NA for a list of df's in R,

I am using the following code, however it throws me an error;

Is there any other way to accomplish this task?

Code

df_list <- lapply(df_list, function(x){
  is.na(x) <- x == "-"
  x
})

Console Output

Error in charToDate(x) : 
  character string is not in a standard unambiguous format

data



df1 <- data.frame(a = c(1, 2, "-"), dates = seq(as.Date("2021/01/01"), 
                                                as.Date("2021/01/03"),
                                                by = "month"),
                  strings = c("hello how are you", "hey man", "-"))

df2 <- data.frame(b = c(3,4, "-"),
                  dates = seq(as.Date("2021/01/01"), 
                              as.Date("2021/01/03"),
                              by = "month"),
                  strings = c("hello how are you", "yoooo", "-")
                  )

df3 <- data.frame(c = c(5, "-", 7),
                  dates = seq(as.Date("2021/01/01"), 
                              as.Date("2021/01/03"),
                              by = "month"),
                  strings = c("hello how are you", "hello world", "-"))


df_list <- list(df1,df2,df3)

Upvotes: 2

Views: 67

Answers (3)

markus
markus

Reputation: 26343

You can use rapply here. The classes argument let's you apply f only to columns of class character.

Similar to akrun's idea, maybe a bit more compact.

rapply(
  df_list,
  f = function(x) replace(x, x == "-", NA),
  classes = "character",
  how = "replace"
)
#[[1]]
#     a      dates           strings
#1    1 2021-01-01 hello how are you
#2    2 2021-01-01           hey man
#3 <NA> 2021-01-01              <NA>

#[[2]]
#     b      dates           strings
#1    3 2021-01-01 hello how are you
#2    4 2021-01-01             yoooo
#3 <NA> 2021-01-01              <NA>

#[[3]]
#     c      dates           strings
#1    5 2021-01-01 hello how are you
#2 <NA> 2021-01-01       hello world
#3    7 2021-01-01              <NA>

Upvotes: 3

ThomasIsCoding
ThomasIsCoding

Reputation: 101317

You can use as.matrix to convert all elements in the list to characters, i.e.,

> lapply(df_list, function(x) replace(x, as.matrix(x) == "-", NA))
[[1]]
     a      dates           strings
1    1 2021-01-01 hello how are you
2    2 2021-01-01           hey man
3 <NA> 2021-01-01              <NA>

[[2]]
     b      dates           strings
1    3 2021-01-01 hello how are you
2    4 2021-01-01             yoooo
3 <NA> 2021-01-01              <NA>

[[3]]
     c      dates           strings
1    5 2021-01-01 hello how are you
2 <NA> 2021-01-01       hello world
3    7 2021-01-01              <NA>

Upvotes: 2

akrun
akrun

Reputation: 887088

The issue would be related to the different type i.e. Date class.

df_list[[1]]$dates == "-"

Error in charToDate(x) : character string is not in a standard unambiguous format

May be we can select only the character columns

df_list2 <- lapply(df_list, function(x) {
      i1 <- sapply(x, is.character)
      x[i1] <- replace(x[i1], x[i1] == "-", NA)
     x
    })

-output

df_list2
#[[1]]
#     a      dates           strings
#1    1 2021-01-01 hello how are you
#2    2 2021-01-01           hey man
#3 <NA> 2021-01-01              <NA>

#[[2]]
#     b      dates           strings
#1    3 2021-01-01 hello how are you
#2    4 2021-01-01             yoooo
#3 <NA> 2021-01-01              <NA>

#[[3]]
#     c      dates           strings
#1    5 2021-01-01 hello how are you
#2 <NA> 2021-01-01       hello world
#3    7 2021-01-01              <NA>

Or it can be also done by converting to character class, but that should be avoided

as.character(df_list[[1]]$dates) == "-"
#[1] FALSE FALSE FALSE

Upvotes: 1

Related Questions