簡體   English   中英

合並列以刪除 NA

[英]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

使用dplyrtidyr一種可能性是:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM