如何用 NA 以外的值填充 merge(..., all = TRUE, ...) 中的缺失值?

Posted

技术标签:

【中文标题】如何用 NA 以外的值填充 merge(..., all = TRUE, ...) 中的缺失值?【英文标题】:How to fill missing values from merge(..., all = TRUE, ...) with a value other than NA? 【发布时间】:2017-09-21 09:50:53 【问题描述】:

简而言之:我正在寻找一种通用方法来用NA 以外的常量填充merge(..., all = TRUE, ...) 中的缺失值。


假设

z <- merge(x, y, all = TRUE, ...)

...并且我希望z 中的所有缺失值(由xy 中的缺失键导致)用(非NA)常量FILL_VALUE 填充。


首先,简单的案例:

FILL_VALUE <- "-"

x <- data.frame(K=1001:1005,
                I=3:7,
                R=c(0.1, 0.2, 0.3, 0.4, 0.5),
                B=c(TRUE, FALSE, TRUE, FALSE, TRUE),
                C=c(0.1+0.2i, 0.3+0.4i, 0.5+0.6i, 0.7+0.8i, 0.9+1.0i))

y <- data.frame(K=1001:1003,
                S1=c("a", "b", "c"),
                S2=c("d", "e", "f"),
                stringsAsFactors = FALSE)

z <- merge(x, y, all = TRUE, by = "K")

## > z
##      K I   R     B        C   S1   S2
## 1 1001 3 0.1  TRUE 0.1+0.2i    a    d
## 2 1002 4 0.2 FALSE 0.3+0.4i    b    e
## 3 1003 5 0.3  TRUE 0.5+0.6i    c    f
## 4 1004 6 0.4 FALSE 0.7+0.8i <NA> <NA>
## 5 1005 7 0.5  TRUE 0.9+1.0i <NA> <NA>

在这种情况下,结果中唯一的 NA 条目是由 merge 引入的条目,因此以下操作可以完成:

z[is.na(z)] <- FILL_VALUE

## > z
##      K I   R     B        C S1 S2
## 1 1001 3 0.1  TRUE 0.1+0.2i  a  d
## 2 1002 4 0.2 FALSE 0.3+0.4i  b  e
## 3 1003 5 0.3  TRUE 0.5+0.6i  c  f
## 4 1004 6 0.4 FALSE 0.7+0.8i  -  -
## 5 1005 7 0.5  TRUE 0.9+1.0i  -  -

现在是这个解决方案失败的案例。

xna <- data.frame(K=1001:1005,
                  I=c(NA, 4:7),
                  R=c(0.1, NA, 0.3, 0.4, 0.5),
                  B=c(TRUE, FALSE, NA, FALSE, TRUE),
                  C=c(0.1+0.2i, 0.3+0.4i, 0.5+0.6i, NA, 0.9+1.0i))

yna <- data.frame(K=1001:1003,
                  S1=c(NA, "b", "c"),
                  S2=c("d", NA, "f"),
                  stringsAsFactors = FALSE)

zna <- merge(xna, yna, all = TRUE, by = "K")
## > zna
##      K  I   R     B        C   S1   S2
## 1 1001 NA 0.1  TRUE 0.1+0.2i <NA>    d
## 2 1002  4  NA FALSE 0.3+0.4i    b <NA>
## 3 1003  5 0.3    NA 0.5+0.6i    c    f
## 4 1004  6 0.4 FALSE       NA <NA> <NA>
## 5 1005  7 0.5  TRUE 0.9+1.0i <NA> <NA>

zna 的期望值是由merge 引入的NA替换为FILL_VALUE 的值;爱荷华州:

## > zna
##      K  I   R     B        C   S1   S2
## 1 1001 NA 0.1  TRUE 0.1+0.2i <NA>    d
## 2 1002  4  NA FALSE 0.3+0.4i    b <NA>
## 3 1003  5 0.3    NA 0.5+0.6i    c    f
## 4 1004  6 0.4 FALSE       NA    -    -
## 5 1005  7 0.5  TRUE 0.9+1.0i    -    -

因此,这是行不通的:

zna[is.na(zna)] <- FILL_VALUE
## > zna
##      K I   R     B        C S1 S2
## 1 1001 - 0.1  TRUE 0.1+0.2i  -  d
## 2 1002 4   - FALSE 0.3+0.4i  b  -
## 3 1003 5 0.3     - 0.5+0.6i  c  f
## 4 1004 6 0.4 FALSE        -  -  -
## 5 1005 7 0.5  TRUE   0.9+1i  -  -

请注意,这个赋值不仅仅是用“-”不恰当地替换一些值;它还改变了几列的类型:

## > zna[, "I"]
## [1] "-" "4" "5" "6" "7"
## > zna[, "B"]
## [1] "TRUE"  "FALSE" "-"     "FALSE" "TRUE" 
## > zna[, "R"]
## [1] "0.1" "-"   "0.3" "0.4" "0.5"
## > zna[, "C"]
## [1] "0.1+0.2i" "0.3+0.4i" "0.5+0.6i" "-"        "0.9+1i"  

【问题讨论】:

也许您可以在“S1”和“S2”列上找到带有!zna$K %in% yna$Kis.na 的行来分配 这个问题的第二个答案似乎为您的问题提供了一种解决方案:***.com/questions/28992362/… merge(x = replace(x = xna, list = is.na(xna), values = "XNA"), y = replace(x = yna, list = is.na(yna), values = "YNA"), by = "K", all = TRUE)怎么样 @kjo,如果你使用Inf 而不是"XNA""YNA" 会怎样 @d.b:有趣的想法,但也有类似的问题。例如,它将整数强制为双精度数。另外(令人惊讶的是),is.infinite 并未针对 DataFrames 实现,因此无法使用zna[is.infinite(zna)] &lt;- NA 恢复原始的NAs,但即使此表达式有效,也无法修复那些Infs被自动强制转换为character。等等等等。 再想一想这个问题,我得出的结论是,下游解决起来太难了;对于merge 的实现者来说,这确实是一份工作。 【参考方案1】:

你可以这样做

> FILL_VALUE <- "-"
> 
> xna <- data.frame(K=1001:1005,
+                   I=c(NA, 4:7),
+                   R=c(0.1, NA, 0.3, 0.4, 0.5),
+                   B=c(TRUE, FALSE, NA, FALSE, TRUE),
+                   C=c(0.1+0.2i, 0.3+0.4i, 0.5+0.6i, NA, 0.9+1.0i))
> 
> yna <- data.frame(K=1001:1003,
+                   S1=c(NA, "b", "c"),
+                   S2=c("d", NA, "f"),
+                   stringsAsFactors = FALSE)
> 
> 
> # add bools
> xna$has_xna <- TRUE
> yna$has_yna <- TRUE
> 
> # merge
> zna <- merge(xna, yna, all = TRUE, by = "K")
> zna
     K  I   R     B        C has_xna   S1   S2 has_yna
1 1001 NA 0.1  TRUE 0.1+0.2i    TRUE <NA>    d    TRUE
2 1002  4  NA FALSE 0.3+0.4i    TRUE    b <NA>    TRUE
3 1003  5 0.3    NA 0.5+0.6i    TRUE    c    f    TRUE
4 1004  6 0.4 FALSE       NA    TRUE <NA> <NA>      NA
5 1005  7 0.5  TRUE 0.9+1.0i    TRUE <NA> <NA>      NA
> 
> # fill in for NAs due to merge
> yna_cols <- colnames(zna) %in% colnames(yna)
> zna[, yna_cols][is.na(zna[, yna_cols]) & is.na(zna$has_yna)] <- FILL_VALUE
> zna$has_yna <- NULL # remove column
> 
> # do the same for xna
> xna_cols <- colnames(zna) %in% colnames(xna)
> zna[, xna_cols][is.na(zna[, xna_cols]) & is.na(zna$has_xna)] <- FILL_VALUE
> zna$has_yna <- NULL # remove column
> 
> # Final results
> zna
     K  I   R     B        C has_xna   S1   S2
1 1001 NA 0.1  TRUE 0.1+0.2i    TRUE <NA>    d
2 1002  4  NA FALSE 0.3+0.4i    TRUE    b <NA>
3 1003  5 0.3    NA 0.5+0.6i    TRUE    c    f
4 1004  6 0.4 FALSE       NA    TRUE    -    -
5 1005  7 0.5  TRUE 0.9+1.0i    TRUE    -    -

上面可以很容易地重写为一个通用的合并函数包装器。另一种选择是将data.tablenomatchon 参数一起使用到[.data.table 函数。

【讨论】:

以上是关于如何用 NA 以外的值填充 merge(..., all = TRUE, ...) 中的缺失值?的主要内容,如果未能解决你的问题,请参考以下文章

在将数据从文件插入表时,如何用 NULL 替换 NA 值?

如何用前一行的值填充空列?

如何用其他数据框的值填充缺失值

如何用从同一个表计算的值填充新列?

如何用特定值填充列中的一系列单元格?

如何用生成器中的值填充 2D Python numpy 数组?