将所有0值替换为NA


144

我有一些数字列的数据框。某行的值为0,在统计分析中应将其视为空值。在R中将所有0值替换为NULL的最快方法是什么?


17
我不认为您希望/可以将其替换为NULL值,但是NA在R术语中达到了这一目的。
Chase 2012年

Answers:


243

将所有零替换为NA:

df[df == 0] <- NA



说明

1.这不是NULL您要替换零的内容。因为它说的?'NULL'

NULL表示R中的空对象

这是唯一的,我想可以看作是最缺乏信息和最空洞的对象。1然后变得不足为奇了

data.frame(x = c(1, NULL, 2))
#   x
# 1 1
# 2 2

也就是说,R不会为此空对象保留任何空间。2同时,看着?'NA'我们看到

NA是长度为1的逻辑常数,其中包含缺失值指示符。NA可以强制为除raw外的任何其他向量类型。

重要的NA是,长度为1,因此R为其保留了一些空间。例如,

data.frame(x = c(1, NA, 2))
#    x
# 1  1
# 2 NA
# 3  2

而且,数据帧结构要求所有列都具有相同数量的元素,以便不存在“空洞”(即NULL值)。

现在,就可以NULL完全删除所有包含至少一个零的行的意义上,在数据框中替换零。当使用,例如,varcov,或cor,实际上等同于第一与替换零NA和设置的值use作为"complete.obs"。但是,通常这不能令人满意,因为这会导致额外的信息丢失。

2.在解决方案中,我没有运行某种循环,而是使用df == 0矢量化。df == 0返回(尝试)相同大小的矩阵df,与所述条目TRUEFALSE。此外,我们还被允许将该矩阵传递给子集[...](请参阅参考资料?'[')。最后,虽然的结果df[df == 0]非常直观,但看起来却很奇怪,无法df[df == 0] <- NA达到预期的效果。赋值运算符<-确实并不总是那么聪明,并且不能以这种方式与某些其他对象一起工作,但对数据帧却是如此。见?'<-'


1集理论中的空集感觉上有某种联系。
2与集合理论的另一个相似之处:空集合是每个集合的子集,但我们不为其保留任何空间。


3
data.table对象的等效语法是什么?
itpetersen 2014年

6
我看到您获得了很多赞成票,但认为这不能适当地覆盖不要求将值设置为“ <NA>”的值为“ 0”的非数字列的边缘情况。
IRTFM 2014年

33

让我假设您的data.frame是不同数据类型的混合,并且并非所有列都需要修改。

仅修改第12到18列(总共21列),只需执行此操作

df[, 12:18][df[, 12:18] == 0] <- NA

这对我
有用,

23

没有该[<-功能的另一种方法:

一个示例数据帧dat(从@Chase的答案中无耻地复制):

dat

  x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0

零可以用NA以下is.na<-函数代替:

is.na(dat) <- !dat


dat

   x  y
1 NA  2
2  1  2
3  1  1
4  2  1
5 NA NA

22

dplyr::na_if() 是一个选择:

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

14
#Sample data
set.seed(1)
dat <- data.frame(x = sample(0:2, 5, TRUE), y = sample(0:2, 5, TRUE))
#-----
  x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0

#replace zeros with NA
dat[dat==0] <- NA
#-----
   x  y
1 NA  2
2  1  2
3  1  1
4  2  1
5 NA NA

12

由于有人要求提供此版本的Data.Table,并且由于给定的data.frame解决方案不适用于data.table,因此,我在下面提供了解决方案。

基本上,使用:=运算符->DT[x == 0, x := NA]

library("data.table")

status = as.data.table(occupationalStatus)

head(status, 10)
    origin destination  N
 1:      1           1 50
 2:      2           1 16
 3:      3           1 12
 4:      4           1 11
 5:      5           1  2
 6:      6           1 12
 7:      7           1  0
 8:      8           1  0
 9:      1           2 19
10:      2           2 40


status[N == 0, N := NA]

head(status, 10)
    origin destination  N
 1:      1           1 50
 2:      2           1 16
 3:      3           1 12
 4:      4           1 11
 5:      5           1  2
 6:      6           1 12
 7:      7           1 NA
 8:      8           1 NA
 9:      1           2 19
10:      2           2 40

2
或者for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA)。有关使用data.table查找和替换值的更详细讨论,请参见此处
JWilliman '16

4

您只能在数字字段(例如,排除因子之类的东西)中替换0NA,但它可以逐列工作:

col[col == 0 & is.numeric(col)] <- NA

使用功能,您可以将其应用于整个数据框:

changetoNA <- function(colnum,df) {
    col <- df[,colnum]
    if (is.numeric(col)) {  #edit: verifying column is numeric
        col[col == -1 & is.numeric(col)] <- NA
    }
    return(col)
}
df <- data.frame(sapply(1:5, changetoNA, df))

尽管您可以将替换为1:5数据框中的列数或1:ncol(df)


我不确定这是正确的解决方案。那第6列及更多内容呢?他们会被削减。
userJT

这就是为什么我建议更换1:51:ncol(df)结尾。我不想使方程过于复杂或难以阅读。
Alium Britt 2015年

但是,如果在第6列和第7列中-数据类型为char,则不应进行任何替换。在我的问题中,我只需要在第12到15列中进行替换,但是整个df就有21列(许多绝对不能触摸)。
userJT

对于数据框,您可以将更1:5改为要更改的列号,例如12:15,但是如果要确认它只会影响数字列,则只需将函数的第二行包装在if语句中,如下所示:if (is.numeric(col)) { col[col == -1 & is.numeric(col)] <- NA }
Alium Britt 2015年

0

如果有人通过谷歌到达这里寻找相反的情况(即如何用0替换data.frame中的所有NA),答案是

df[is.na(df)] <- 0

要么

使用dplyr / tidyverse

library(dplyr)
mtcars %>% replace(is.na(.), 0)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.