[英]Combine column to remove NA's
我在 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]
調用列。
任何幫助,將不勝感激。
謝謝
基於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))
您可以使用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
我會將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
),因為上面的第一個參數不是數據框。
這是一個更通用(但更簡單)的解決方案,它擴展到具有無序 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)
來自動執行此操作。
像這樣的東西?
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
max 也有效。 也適用於字符串向量。
cbind(data[1], mycol=apply(data[-1], 1, max, na.rm=T))
在相關鏈接( 在 paste() 中抑制na.rm
)中,我展示了一個帶有na.rm
選項的paste
版本(不幸的名稱是paste5
)。
有了這個代碼變成
cols <- c("x", "y", "z")
cbind.data.frame(a = data$a, mycol = paste2(data[, cols], na.rm = TRUE))
paste5
的輸出是一個字符,如果你有字符數據, paste5
可以工作,否則你需要強制轉換為你想要的類型。
雖然這不是 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
使用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。
如果你想堅持基地,
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))
data[is.na(data)]<-","
data$mycol<-paste0(data$x,data$y,data$z)
data$mycol <- gsub(',','',data$mycol)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.