Zet NA op 0 in R

Na het samenvoegen van een dataframe met een ander heb ik af en toe willekeurige NA’s over. Ik wil deze NA’s op 0 zetten zodat ik er berekeningen mee kan uitvoeren.

Ik probeer dit te doen met:

   bothbeams.data = within(bothbeams.data, {
      bothbeams.data$x.x = ifelse(is.na(bothbeams.data$x.x) == TRUE, 0, bothbeams.data$x.x)
      bothbeams.data$x.y = ifelse(is.na(bothbeams.data$x.y) == TRUE, 0, bothbeams.data$x.y)
    })

Waar $x.x de ene kolom is en $x.y de andere is natuurlijk, maar dit lijkt niet te werken.


Antwoord 1, autoriteit 100%

Je kunt gewoon de uitvoer van is.nagebruiken om direct te vervangen door een subinstelling:

bothbeams.data[is.na(bothbeams.data)] <- 0

Of met een reproduceerbaar voorbeeld:

dfr <- data.frame(x=c(1:3,NA),y=c(NA,4:6))
dfr[is.na(dfr)] <- 0
dfr
  x y
1 1 0
2 2 4
3 3 5
4 0 6

Wees echter voorzichtig met het gebruik van deze methode op een dataframe dat factoren bevat die ook ontbrekende waarden hebben:

> d <- data.frame(x = c(NA,2,3),y = c("a",NA,"c"))
> d[is.na(d)] <- 0
Warning message:
In `[<-.factor`(`*tmp*`, thisvar, value = 0) :
  invalid factor level, NA generated

Het “werkt”:

> d
  x    y
1 0    a
2 2 <NA>
3 3    c

…maar u zult in dit geval waarschijnlijk alleen de numerieke kolommen willen wijzigen, in plaats van het hele gegevensframe. Zie bijvoorbeeld het antwoord hieronder met dplyr::mutate_if.


Antwoord 2, autoriteit 31%

Een oplossing die mutate_allvan dplyrgebruikt voor het geval je dat wilt toevoegen aan je dplyr-pipeline:

library(dplyr)
df %>%
  mutate_all(funs(ifelse(is.na(.), 0, .)))

Resultaat:

  A B C
1  0 0 0
2  1 0 0
3  2 0 2
4  3 0 5
5  0 0 2
6  0 0 1
7  1 0 1
8  2 0 5
9  3 0 2
10 0 0 4
11 0 0 3
12 1 0 5
13 2 0 5
14 3 0 0
15 0 0 1

Als je in ieder geval alleen de NA’s in numerieke kolommen wilt vervangen, wat naar ik aanneem het geval is bij modelleren, kun je mutate_ifgebruiken:

library(dplyr)
df %>%
  mutate_if(is.numeric, funs(ifelse(is.na(.), 0, .)))

of in grondtal R:

replace(is.na(df), 0)

Resultaat:

  A    B C
1  0    0 0
2  1 <NA> 0
3  2    0 2
4  3 <NA> 5
5  0    0 2
6  0 <NA> 1
7  1    0 1
8  2 <NA> 5
9  3    0 2
10 0 <NA> 4
11 0    0 3
12 1 <NA> 5
13 2    0 5
14 3 <NA> 0
15 0    0 1

Bijwerken

met dplyr 1.0.0wordt acrossgeïntroduceerd:

library(dplyr)
# Replace `NA` for all columns
df %>%
  mutate(across(everything(), ~ ifelse(is.na(.), 0, .)))
# Replace `NA` for numeric columns
df %>%
  mutate(across(where(is.numeric), ~ ifelse(is.na(.), 0, .)))

Gegevens:

set.seed(123)
df <- data.frame(A=rep(c(0:3, NA), 3), 
                 B=rep(c("0", NA), length.out = 15), 
                 C=sample(c(0:5, NA), 15, replace = TRUE))

Antwoord 3, autoriteit 2%

Om aan James’ voorbeeld toe te voegen, het lijkt erop dat je altijd een tussenliggende moet maken bij het uitvoeren van berekeningen op NA-bevattende dataframes.

Bijvoorbeeld, twee kolommen (A en B) bij elkaar optellen uit een dataframe dfr:

temp.df <- data.frame(dfr) # copy the original
temp.df[is.na(temp.df)] <- 0
dfr$C <- temp.df$A + temp.df$B # or any other calculation
remove('temp.df')

Als ik dit doe, gooi ik het tussenproduct daarna weg met remove/rm.


Antwoord 4

Je kunt replace_na()uit het tidyrpakket

gebruiken

df %>% replace_na(list(column1 = 0, column2 = 0)


Antwoord 5

Waarom probeer je dit niet

 na.zero <- function (x) {
        x[is.na(x)] <- 0
        return(x)
    }
    na.zero(df)

Other episodes