如何用 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
中的所有缺失值(由x
或y
中的缺失键导致)用(非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$K
和is.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)] <- NA
恢复原始的NA
s,但即使此表达式有效,也无法修复那些Inf
s被自动强制转换为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.table
与nomatch
和on
参数一起使用到[.data.table
函数。
【讨论】:
以上是关于如何用 NA 以外的值填充 merge(..., all = TRUE, ...) 中的缺失值?的主要内容,如果未能解决你的问题,请参考以下文章