Mihail
Mihail

Reputation: 827

Replace NA with " ", but only in character columns

I have a large dataset with ~200 columns of various types. I need to replace NA values with "", but only in character columns.

Using the dummy data table

DT <- data.table(x = c(1, NA, 2),
                y = c("a", "b", NA))

> DT
    x    y
1:  1    a
2: NA    b
3:  2 <NA>

> str(DT)
Classes ‘data.table’ and 'data.frame':  3 obs. of  2 variables:
 $ x: num  1 NA 2
 $ y: chr  "a" "b" NA

I have tried the following for-loop with a condition, but it doesn't work.

for (i in names(DT)) {
  if (class(DT$i) == "character") {
    DT[is.na(i), i := ""]
  }
}

The loop runs with no errors, but doesn't change the DT.

The expected output I am looking for is this:

    x y
1:  1 a
2: NA b
3:  2  

The solution doesn't necessarily have to involve a loop, but I couldn't think of one.

Upvotes: 1

Views: 1993

Answers (2)

IceCreamToucan
IceCreamToucan

Reputation: 28685

DT[,  lapply(.SD, function(x){if(is.character(x)) x[is.na(x)] <-  ' '; x})]

Or, if you don't like typing function(x)

library(purrr)
DT[,  map(.SD, ~{if(is.character(.x)) .x[is.na(.x)] <-  ' '; .x})]

To replace

DT[, names(DT) :=  map(.SD, ~{if(is.character(.x)) .x[is.na(.x)] <-  ' '; .x})]

Upvotes: 2

joran
joran

Reputation: 173577

One option if you don't mind using dplyr:

na_to_space <- function(x) ifelse(is.na(x)," ",x)
> DT %>% mutate_if(.predicate = is.character,.funs = na_to_space)
   x y
1  1 a
2 NA b
3  2  

Upvotes: 3

Related Questions