Replace all 0 values to NA
Let me assume that your data.frame is a mix of different datatypes and not all columns need to be modified.
to modify only columns 12 to 18 (of the total 21), just do this
df[, 12:18][df[, 12:18] == 0] <- NA
Replacing all zeroes to NA:
df[df == 0] <- NA
Explanation
1. It is not NULL
what you should want to replace zeroes with. As it says in ?'NULL'
,
NULL represents the null object in R
which is unique and, I guess, can be seen as the most uninformative and empty object.1 Then it becomes not so surprising that
data.frame(x = c(1, NULL, 2))
# x
# 1 1
# 2 2
That is, R does not reserve any space for this null object.2 Meanwhile, looking at ?'NA'
we see that
NA is a logical constant of length 1 which contains a missing value indicator. NA can be coerced to any other vector type except raw.
Importantly, NA
is of length 1 so that R reserves some space for it. E.g.,
data.frame(x = c(1, NA, 2))
# x
# 1 1
# 2 NA
# 3 2
Also, the data frame structure requires all the columns to have the same number of elements so that there can be no "holes" (i.e., NULL
values).
Now you could replace zeroes by NULL
in a data frame in the sense of completely removing all the rows containing at least one zero. When using, e.g., var
, cov
, or cor
, that is actually equivalent to first replacing zeroes with NA
and setting the value of use
as "complete.obs"
. Typically, however, this is unsatisfactory as it leads to extra information loss.
2. Instead of running some sort of loop, in the solution I use df == 0
vectorization. df == 0
returns (try it) a matrix of the same size as df
, with the entries TRUE
and FALSE
. Further, we are also allowed to pass this matrix to the subsetting [...]
(see ?'['
). Lastly, while the result of df[df == 0]
is perfectly intuitive, it may seem strange that df[df == 0] <- NA
gives the desired effect. The assignment operator <-
is indeed not always so smart and does not work in this way with some other objects, but it does so with data frames; see ?'<-'
.
1 The empty set in the set theory feels somehow related.
2 Another similarity with the set theory: the empty set is a subset of every set, but we do not reserve any space for it.
dplyr::na_if()
is an option:
library(dplyr)
df <- data_frame(col1 = c(1, 2, 3, 0),
col2 = c(0, 2, 3, 4),
col3 = c(1, 0, 3, 0),
col4 = c('a', 'b', 'c', 'd'))
na_if(df, 0)
# A tibble: 4 x 4
col1 col2 col3 col4
<dbl> <dbl> <dbl> <chr>
1 1 NA 1 a
2 2 2 NA b
3 3 3 3 c
4 NA 4 NA d