这是this earlier question的扩展。如何将数据框的两列组合为
data <- data.frame('a' = c('A','B','C','D','E'),
'x' = c("t",2,NA,NA,NA),
'y' = c(NA,NA,NA,4,"r"))
显示为
'a' 'x' 'y'
A t NA
B 2 NA
C NA NA
D NA 4
E NA r
获取
'a' 'mycol'
A t
B 2
C NA
D 4
E r
我试过这个
cbind(data[1], mycol = na.omit(unlist(data[-1])))
但它显然没有保留NA
行。
答案 0 :(得分:0)
您可以使用ifelse
来完成此操作:
data$mycol <- ifelse(!is.na(data$x), data$x, data$y)
> data
## a x y mycol
## 1 A 1 NA 1
## 2 B 2 NA 2
## 3 C NA NA NA
## 4 D NA 4 4
## 5 E NA 5 5
答案 1 :(得分:0)
按照你的逻辑,你可以做到:
cbind(data[1], mycol = unlist(apply(data[2:3], 1, function(i) ifelse(
length(is.na(i))==length(i),
na.omit(i),
NA)
)))
# a mycol
#1 A 1
#2 B 2
#3 C NA
#4 D 4
#5 E 5
答案 2 :(得分:0)
这已经间接地解决了here。这是一个基于此的简单解决方案:
data$mycol <- coalesce(data$x, data$y)
答案 3 :(得分:0)
将答案扩展到任意数量的列,并使用我发现的整齐max.col()
函数,这要归功于这个问题:
coalesce <- function(value_matrix) {
value_matrix <- as.matrix(value_matrix)
first_non_missing <- max.col(!is.na(value_matrix), ties.method = "first")
indices <- cbind(
row = seq_len(nrow(value_matrix)),
col = first_non_missing
)
value_matrix[indices]
}
data$mycol <- coalesce(data[, c('x', 'y')])
data
# a x y mycol
# 1 A 1 NA 1
# 2 B 2 NA 2
# 3 C NA NA NA
# 4 D NA 4 4
# 5 E NA 5 5
max.col(..., ties.method = "first")
为每一行返回具有最大值的第一列的索引。由于我们在逻辑矩阵上使用它,因此最大值通常是TRUE
。因此,我们将获得每行的第一个非NA
值。如果整行是NA
,那么我们会根据需要获得NA
值。
之后,该函数使用行列索引矩阵来对值进行子集化。
修改强>
与mrip's coalesce相比,我的max.col
在有一些长列时速度较慢,但在有很多短列时速度较快。
coalesce_reduce <- function(...) {
Reduce(function(x, y) {
i <- which(is.na(x))
x[i] <- y[i]
x},
list(...))
}
coalesce_maxcol <- function(...) {
value_matrix <- cbind(...)
first_non_missing <- max.col(!is.na(value_matrix), ties.method = "first")
indices <- cbind(
row = seq_len(nrow(value_matrix)),
col = first_non_missing
)
value_matrix[indices]
}
set.seed(100)
wide <- replicate(
1000,
{sample(c(NA, 1:10), 10, replace = TRUE)},
simplify = FALSE
)
long <- replicate(
10,
{sample(c(NA, 1:10), 1000, replace = TRUE)},
simplify = FALSE
)
microbenchmark(
do.call(coalesce_reduce, wide),
do.call(coalesce_maxcol, wide),
do.call(coalesce_reduce, long),
do.call(coalesce_maxcol, long)
)
# Unit: microseconds
# expr min lq mean median uq max neval
# do.call(coalesce_reduce, wide) 1879.460 1953.5695 2136.09954 2007.303 2152.654 5284.583 100
# do.call(coalesce_maxcol, wide) 403.604 423.5280 490.40797 433.641 456.583 2543.580 100
# do.call(coalesce_reduce, long) 36.829 41.5085 45.75875 43.471 46.942 79.393 100
# do.call(coalesce_maxcol, long) 80.903 88.1475 175.79337 92.374 101.581 3438.329 100