I have a factor variable in my data frame with values where in the original CSV "NA" was intended to mean simply "None", not missing data. Hence I want replace every value in the given column with "None" factor value. I tried this:

DF$col[is.na(DF$col)] <- "None"

but this throws the following error:

Warning message:
In `[<-.factor`(`*tmp*`, is.na(DF$col), value = c(NA, NA,  :
  invalid factor level, NA generated

I guess this is because originally there is no "None" factor level in the column, but is it the true reason? If so, how could I add a new "None" level to the factor?

(In case you would ask why didn't I convert NAs into "None" in the read.csv phase: in other columns NA really does mean missing data).

  • $\begingroup$ I'm voting to close this question as off-topic because it belongs on Stack Overflow $\endgroup$ – Sean Owen Dec 15 '18 at 5:14

You need to add "None" to the factor level and refactor the column DF$col. I added an example script using the iris dataset.

df <- iris

# set 20 Species to NA
s <- sample(nrow(df), 20)
df$Species[s] <- NA

# Get levels and add "None"
levels <- levels(df$Species)
levels[length(levels) + 1] <- "None"

# refactor Species to include "None" as a factor level
# and replace NA with "None"
df$Species <- factor(df$Species, levels = levels)
df$Species[is.na(df$Species)] <- "None"

You can use this function :


fct_explicit_na(DF$col, na_level = "None")


It can be used within the mutate function and piped to edit DF directly:

library(tidyverse) # for tidy data packages, automatically loads dplyr
library(magrittr) # for piping
DF %<>% mutate(cols = fct_explicit_na(col, na_level = "None"))

Note that "col" needs to be a factor for this to work.

  • 1
    $\begingroup$ The basic idea is right but it looks like there are errors in the code on line 3 of usage. I would try to implement a working example and make sure it runs properly. $\endgroup$ – readyready15728 May 27 '19 at 4:43
  • 1
    $\begingroup$ @readyready15728 I'm seeing that %<>% should be %<% instead. $\endgroup$ – Gabriel L. Jul 4 '19 at 22:00
  • $\begingroup$ Cool. Can you still edit? $\endgroup$ – readyready15728 Jul 5 '19 at 4:20

Your original approach was right, and your intuition about the missing level too. To do what you want you just needed to add add the level "None".

#Create a factor for the example

levels(x)<-c(levels(x),"None")  #Add the extra level to your factor
x[is.na(x)] <- "None"           #Change NA to "None"

I'd just do an NA assign


vec <- c('1', '2', NA, '4')
vec <- chr(vec) # make it a character vector first

vec %na<-% 0


Then turn it into a factor again if you really need to (eg for plotting). or you could first add the factor level (as done above) and overwrite NAs


change data type

d[is.na(d)] <-"None"

Not the answer you're looking for? Browse other questions tagged or ask your own question.