我在R中有一些列,对于每一行,其中一列只有一个值,其余的将是NA。我想将这些组合成一个具有非NA值的列。有谁知道这样做的简单方法。例如,我可以如下:
data <- data.frame('a' = c('A','B','C','D','E'),
'x' = c(1,2,NA,NA,NA),
'y' = c(NA,NA,3,NA,NA),
'z' = c(NA,NA,NA,4,5))
所以我会
'a' 'x' 'y' 'z'
A 1 NA NA
B 2 NA NA
C NA 3 NA
D NA NA 4
E NA NA 5
我会得到
'a' 'mycol'
A 1
B 2
C 3
D 4
E 5
包含NA的列的名称会根据查询中较早的代码而更改,因此我无法显式调用列名,但是我将包含NA的列的列名存储为向量,例如在此示例中cols <- c('x','y','z')
,因此可以使用data[, cols]
调用列。
任何帮助都将不胜感激。
由于
答案 0 :(得分:20)
基于dplyr::coalesce
的解决方案可以是:
data %>% mutate(mycol = coalesce(x,y,z)) %>%
select(a, mycol)
# a mycol
# 1 A 1
# 2 B 2
# 3 C 3
# 4 D 4
# 5 E 5
数据强>
data <- data.frame('a' = c('A','B','C','D','E'),
'x' = c(1,2,NA,NA,NA),
'y' = c(NA,NA,3,NA,NA),
'z' = c(NA,NA,NA,4,5))
答案 1 :(得分:18)
您可以使用unlist
将列转换为一个向量。之后,na.omit
可用于删除NA
。
cbind(data[1], mycol = na.omit(unlist(data[-1])))
a mycol
x1 A 1
x2 B 2
y3 C 3
z4 D 4
z5 E 5
答案 2 :(得分:11)
我会将rowSums()
与na.rm = TRUE
参数一起使用:
cbind.data.frame(a=data$a, mycol = rowSums(data[, -1], na.rm = TRUE))
给出:
> cbind.data.frame(a=data$a, mycol = rowSums(data[, -1], na.rm = TRUE))
a mycol
1 A 1
2 B 2
3 C 3
4 D 4
5 E 5
您必须直接调用该方法(cbind.data.frame
),因为上面的第一个参数不是数据框。
答案 3 :(得分:11)
这是一个更通用(但更简单)的解决方案,它扩展到具有无序NA的所有列类型(因子,字符等)。该策略只是使用is.na
将其他列的非NA值合并到合并列中以进行索引:
data$m = data$x # your new merged column start with x
data$m[!is.na(data$y)] = data$y[!is.na(data$y)] # merge with y
data$m[!is.na(data$z)] = data$z[!is.na(data$z)] # merge with z
> data
a x y z m
1 A 1 NA NA 1
2 B 2 NA NA 2
3 C NA 3 NA 3
4 D NA NA 4 4
5 E NA NA 5 5
请注意,如果同一行中有多个非NA值,则会覆盖m
中的现有值。如果您有很多列,则可以通过循环colnames(data)
来自动执行此操作。
答案 4 :(得分:4)
这样的东西?
data.frame(a=data$a, mycol=apply(data[,-1],1,sum,na.rm=TRUE))
给出:
a mycol
1 A 1
2 B 2
3 C 3
4 D 4
5 E 5
答案 5 :(得分:1)
max也有效。也适用于字符串向量。
cbind(data[1], mycol=apply(data[-1], 1, max, na.rm=T))
答案 6 :(得分:0)
在相关链接(suppress NAs in paste())中,我提供的paste
版本带有na.rm
选项(不幸的名称为paste5
)。
这样代码变成
cols <- c("x", "y", "z")
cbind.data.frame(a = data$a, mycol = paste2(data[, cols], na.rm = TRUE))
paste5
的输出是一个字符,如果您有字符数据,则该字符有效,否则您需要强制转换为您想要的类型。
答案 7 :(得分:0)
虽然这不是OP案例,但似乎有些人喜欢基于总和的方法,如何在均值和模式下思考,使答案更具普遍性。这个答案与标题相符,这是许多人会发现的。
data <- data.frame('a' = c('A','B','C','D','E'),
'x' = c(1,2,NA,NA,9),
'y' = c(NA,6,3,NA,5),
'z' = c(NA,NA,NA,4,5))
splitdf<-split(data[,c(2:4)], seq(nrow(data[,c(2:4)])))
data$mean<-unlist(lapply(splitdf, function(x) mean(unlist(x), na.rm=T) ) )
data$mode<-unlist(lapply(splitdf, function(x) {
tab <- tabulate(match(x, na.omit(unique(unlist(x) ))));
paste(na.omit(unique(unlist(x) ))[tab == max(tab) ], collapse = ", " )}) )
data
a x y z mean mode
1 A 1 NA NA 1.000000 1
2 B 2 6 NA 4.000000 2, 6
3 C NA 3 NA 3.000000 3
4 D NA NA 4 4.000000 4
5 E 9 5 5 6.333333 5
答案 8 :(得分:0)
使用dplyr
和tidyr
的一种可能性是:
data %>%
gather(variables, mycol, -1, na.rm = TRUE) %>%
select(-variables)
a mycol
1 A 1
2 B 2
8 C 3
14 D 4
15 E 5
此处将数据从宽格式转换为长格式,但不包括该操作的第一列并删除了NA。
答案 9 :(得分:0)
如果你想坚持下去,
$0x8088A8C0