4
$\begingroup$

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).

$\endgroup$

closed as off-topic by Sean Owen Dec 15 '18 at 5:14

  • This question does not appear to be about data science, within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

  • $\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
5
$\begingroup$

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
set.seed(1234)
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"
$\endgroup$
9
$\begingroup$

You can use this function :

forcats::fct_explicit_na

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

Usage

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.

$\endgroup$
  • 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 at 4:43
  • 1
    $\begingroup$ @readyready15728 I'm seeing that %<>% should be %<% instead. $\endgroup$ – Gabriel L. Jul 4 at 22:00
  • $\begingroup$ Cool. Can you still edit? $\endgroup$ – readyready15728 Jul 5 at 4:20
2
$\begingroup$

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
x<-factor(c("S",NA,"M","S","S","S",NA,NA,"S","M","S",NA,"M","S",NA,"S","S",NA,"M","S",NA,"M"))

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

I'd just do an NA assign

library(roperators)

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

vec %na<-% 0

print(vec)

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

$\endgroup$
-2
$\begingroup$

change data type

d=as.matrix(d)
d[is.na(d)] <-"None"
d=as.data.frame(d)
$\endgroup$

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