【问题标题】:Quick replace of NA - an error or warning快速替换 NA - 错误或警告
【发布时间】:2018-01-16 08:54:49
【问题描述】:

我有一个名为“mat”的 49952 obs 的大 data.frame。 7597 个变量,我正在尝试用零替换 NA。以下是我的 data.frame 的示例:

    A   B   C   E   F   D   Q   Z   . . .
1   1   1   0   NA  NA  0   NA  NA
2   0   0   1   NA  NA  0   NA  NA
3   0   0   0   NA  NA  1   NA  NA
4   NA  NA  NA  NA  NA  NA  NA  NA
5   0   1   0   1   NA  0   NA  NA 
6   1   1   1   0   NA  0   NA  NA
7   0   0   1   0   NA  1   NA  NA 
.
.
.

我需要非常快速的工具来替换它们。结果应如下所示:

    A   B   C   E   F   D   Q   Z   . . .
1   1   1   0   0   0   0   0   0
2   0   0   1   0   0   0   0   0 
3   0   0   0   0   0   1   0   0
4   0   0   0   0   0   0   0   0
5   0   1   0   1   0   0   0   0 
6   1   1   1   0   0   0   0   0
7   0   0   1   0   0   1   0   0 
.
.
.

我已经尝试过 lapply(mat, function(x){replace(x, is.na(x),0)}) - 没用 - mat[is.na(mat)] <- 0 - 错误而且可能太慢 - 还有link - 也没有用。

@Sotos 已经建议我plyr::rbind.fill(lapply(L, as.data.frame)),但它没有用,因为它生成了 379485344 个观察值和 1 个变量(即 49952x7597)的 data.frame,所以我还必须将它转换回来。有没有更好的方法来做到这一点?

我的data.frame的真实结构:

> str(mat)
'data.frame':   49952 obs. of  7597 variables:
 $ 6794602   : num  1 NA NA NA NA 0 0 0 0 0 ...
 $ 1008667   : num  NA 1 0 NA NA 0 0 0 0 0 ...
 $ 8009082   : num  NA 0 1 NA NA NA NA NA NA NA ...
 $ 6740421   : num  NA NA NA 1 NA 0 0 0 0 0 ...
 $ 6777805   : num  NA NA NA NA 1 NA NA NA NA NA ...
 $ 1001682   : num  NA NA NA NA NA 0 0 0 0 0 ...
 $ 1001990   : num  NA NA NA NA NA 0 0 0 0 0 ...
 $ 1002541   : num  NA NA NA NA NA 0 0 0 0 0 ...
 $ 1002790   : num  NA NA NA NA NA 0 0 0 0 0 ...

注意:

当我尝试mat[is.na(mat)] <- 0 时出现警告:

> mat[is.na(mat)] <- 0
Warning messages:
1: In `[<-.factor`(`*tmp*`, thisvar, value = 0) :
  invalid factor level, NA generated
2: In `[<-.factor`(`*tmp*`, thisvar, value = 0) :
  invalid factor level, NA generated
> nlevels(mat)
[1] 0

使用mat[is.na(mat)] &lt;- 0后的Data.frame mat:

> str(mat)
'data.frame':   49952 obs. of  7597 variables:
 $ 6794602   : num  1 0 0 0 0 0 0 0 0 0 ...
 $ 1008667   : num  0 1 0 0 0 0 0 0 0 0 ...
 $ 8009082   : num  0 0 1 0 0 0 0 0 0 0 ...
 $ 6740421   : num  0 0 0 1 0 0 0 0 0 0 ...
 $ 6777805   : num  0 0 0 0 1 0 0 0 0 0 ...
 $ 1001682   : num  0 0 0 0 0 0 0 0 0 0 ...
 $ 1001990   : num  0 0 0 0 0 0 0 0 0 0 ...
 $ 1002541   : num  0 0 0 0 0 0 0 0 0 0 ...
 $ 1002790   : num  0 0 0 0 0 0 0 0 0 0 ...

所以问题是:

  1. 有没有其他快速的方法来替换 NA?
  2. 警告很重要吗?因为使用mat[is.na(mat)] &lt;- 0后的数据看起来和我想要的一样,但是值太多了,所以无法检查是否可以。

【问题讨论】:

  • mat[is.na(mat)] = 0 应该是最快的方法,放下手(在密集矩阵上)。如果不是,那是 R 中的一个明显错误……
  • 这是一个警告而不是错误,它很好地解释了正在发生的事情,对吧?如果您对数据中包含因子感到惊讶,不妨试试View(mat[sapply(mat, is.factor)])str,而不是那里的View
  • @Frank 这个问题包含str(mat) 的输出,没有任何因素。但是警告消息根本不适合该输出。
  • @Konrad OP 截断了 str 输出。试试str(as.data.frame(replicate(7597, 1, simplify=FALSE)))——首先,OP 向我们展示的比他们看到的要少;其次,即使是完整显示的输出也不会显示所有 7597 列。无论如何,我们不能确定什么时候 OP 只提供了他们数据的一瞥而不是一个很好的例子......
  • @Frank @KonradRudolph 我认为不应该有任何因素我从:'data.frame': 199235 obs. of 3 variables: $ Invoice_Date: Factor w/ 627 levels $ SKU : Factor w/ 53113 levels $ CustomerID : Factor w/ 55945 levels 将它分成 627 个数据帧,根据 Invoice_Date 并使用 droplevels 来简化计算和然后我在列中制作了 SKU 的频率数据帧,在行中制作了 CustomerID,然后我使用mat &lt;- rbindlist(cop.data1, fill=T) 将其重新组合在一起(我不需要 CusotmerID),我得到了 data.frame mat

标签: r dataframe na


【解决方案1】:

尝试以下方法:

mat %>% replace(is.na(.), 0)

【讨论】:

  • 它比mat[is.na(mat)] &lt;- 0 需要更长的时间,但也许我会让它运行一夜,看看是否还会出现警告。编辑:它需要更长的时间 - 警告。所以正如我上面写的,我想我会忽略这个警告。
  • 您能否检查以下问题以了解该警告消息?可能有助于解决。 stackoverflow.com/a/16820025/8382207
【解决方案2】:

如果怀疑您的某些列是因子,您可以使用以下代码检测并将它们更改为数字。

inx <- sapply(mat, inherits, "factor")
mat[inx] <- lapply(mat[inx], function(x) as.numeric(as.character(x)))

然后尝试以下操作。

mat[] <- lapply(mat, function(x) {x[is.na(x)] <- 0; x})
mat

这是数据。

mat <-
structure(list(A = c(1L, 0L, 0L, NA, 0L, 1L, 0L), B = c(1L, 0L, 
0L, NA, 1L, 1L, 0L), C = c(0L, 1L, 0L, NA, 0L, 1L, 1L), E = c(NA, 
NA, NA, NA, 1L, 0L, 0L), F = c(NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_, NA_real_), D = c(0L, 0L, 1L, NA, 
0L, 0L, 1L), Q = c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_), Z = c(NA_real_, NA_real_, NA_real_, NA_real_, 
NA_real_, NA_real_, NA_real_)), .Names = c("A", "B", "C", "E", 
"F", "D", "Q", "Z"), row.names = c("1", "2", "3", "4", "5", "6", 
"7"), class = "data.frame")

【讨论】:

  • 再次警告消息:Warning messages: 1: In [(*tmp*, is.na(x), value = 0) : invalid factor level, NA generated 2: In [(*tmp*, is.na(x), value = 0) : invalid factor level, NA generated也许我会忽略警告,这不是其他情况下的错误。
  • @MartinaZapletalová 如果str(mat) 的输出是正确的,那不应该发生,因为所有列都属于numeric 类。你确定所有这 7597 个变量都是numeric 吗?如果其中两个是因素,您可能需要先将它们转换为numeric
  • 所以我尝试了这个:a &lt;- 0 for (i in 1:ncol(mat)){ if (class(mat[[i]]) == "numeric"){ a &lt;- a+1 } else { a &lt;- a+1 print(i) } } 并发现 mat[[2260]] 和 mat[[2261]] 存在问题,所以我查看了它,你是对的,它们是因素,但是我不明白这是怎么发生的。
  • @MartinaZapletalová 好的,我将使用代码编辑我的答案,以便您以自动方式消除这些因素。
【解决方案3】:

看我的详细回答here

#install.packages("xlsx")
library(xlsx)
extracted_df <- read.xlsx("test.xlsx", sheetName='Sheet1', stringsAsFactors=FALSE)
# Replace all NAs in a data frame with "G" character
extracted_df[is.na(extracted_df)] <- "G"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    • 2016-02-08
    • 2011-05-27
    • 2011-03-12
    相关资源
    最近更新 更多