【问题标题】:Replace all 0 values to NA将所有 0 值替换为 NA
【发布时间】:2012-06-17 17:10:52
【问题描述】:

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

【问题讨论】:

  • 我认为您不希望/可以用 NULL 值替换,但 NA 在 R 术语中用于此目的。

标签: r r-faq


【解决方案1】:

将所有零替换为 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 替换零,即完全删除包含至少一个零的所有行。例如,当使用varcovcor 时,这实际上相当于首先用NA 替换零并将use 的值设置为"complete.obs"。然而,这通常不能令人满意,因为它会导致额外的信息丢失。

2. 在解决方案中,我使用df == 0 向量化,而不是运行某种循环。 df == 0 返回(尝试一下)一个与df 大小相同的矩阵,其中包含TRUEFALSE 条目。此外,我们还可以将此矩阵传递给子集[...](参见?'[')。最后,虽然df[df == 0] 的结果非常直观,但df[df == 0] &lt;- NA 给出了预期的效果似乎很奇怪。赋值运算符&lt;- 确实并不总是那么聪明,并且不能以这种方式与其他一些对象一起工作,但它可以与数据帧一起工作;见?'&lt;-'


1 集合论中的空集感觉有些相关。
2 与集合论的另一个相似之处:空集是每个集的子集,但我们不为它保留任何空间。

【讨论】:

  • data.table 对象的等效语法是什么?
  • 我看到您获得了很多选票,但认为这不能适当地涵盖值为“0”且未要求设置为 的非数字列的边缘情况.
【解决方案2】:
#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

【讨论】:

    【解决方案3】:

    没有[&lt;- 函数的替代方法:

    一个样本数据框dat(无耻地从@Chase的答案中复制):

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

    可以通过is.na&lt;- 函数将零替换为NA

    is.na(dat) <- !dat
    
    
    dat
    
       x  y
    1 NA  2
    2  1  2
    3  1  1
    4  2  1
    5 NA NA
    

    【讨论】:

      【解决方案4】:

      您只能在数字字段中将0 替换为NA(即排除因子等内容),但它可以逐列使用:

      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 列及更多列呢?他们会被砍掉。
      • 这就是为什么我建议最后用1:ncol(df) 替换1:5。我不想让方程式过于复杂或难以阅读。
      • 但是如果在第 6 列和第 7 列中 - 数据类型是 char 并且不应该进行替换。在我的问题中,我只需要在第 12 到 15 列中进行替换,但整个 df 有 21 列(许多根本不能被触及)。
      • 对于您的数据框,您可以将1:5 更改为您想要更改的列号,例如12:15,但如果您想确认它只会影响数字列,那么只需将if 语句中函数的第二行,如下所示:if (is.numeric(col)) { col[col == -1 &amp; is.numeric(col)] &lt;- NA }.
      【解决方案5】:

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

      仅修改第 12 到 18 列(总共 21 列),只需这样做

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

      【讨论】:

      • 这对我有用,而接受的答案却没有
      • 这行得通,而且比接受的答案更灵活。
      • [] 的双子集很棒!如此明显,但仍然如此隐蔽:)
      • @userJT - 如果我想选择名称而不是位置的列怎么办?例如300 列名称:age1,age2,age3,age4 ...... age300
      【解决方案6】:

      因为有人要求这个的 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
      

      【讨论】:

      • for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA)。有关使用 data.table 查找和替换值的更详细讨论,请参阅 here
      【解决方案7】:

      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
      

      【讨论】:

        【解决方案8】:

        如果有人通过谷歌到达这里寻找对面(即如何将data.frame中的所有NA替换为0),答案是

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

        使用 dplyr / tidyverse

        library(dplyr)
        mtcars %>% replace(is.na(.), 0)
        

        【讨论】:

          【解决方案9】:

          如果你和我一样,在想知道如何用 NA 替换数据框中的所有值时来到这里,那就是:

          df[,] &lt;- NA

          【讨论】:

            猜你喜欢
            • 2023-01-19
            • 2019-05-30
            • 2020-11-19
            • 2017-11-27
            • 2021-07-02
            • 1970-01-01
            • 2016-12-04
            相关资源
            最近更新 更多