web-dev-qa-db-ja.com

列を結合してNAを削除する

Rにはいくつかの列があり、各行の値はいずれか1つだけになり、残りはNAになります。これらを、NA以外の値を持つ1つの列に結合したいと思います。誰でもこれを行う簡単な方法を知っていますか?たとえば、次のようにできます。

_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]_を使用して列を呼び出すことができます。

任意の助けをいただければ幸いです。

ありがとう

34
user1165199

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))
22
MKR

unlistを使用して、列を1つのベクトルに変換できます。その後、na.omitを使用してNAsを削除できます。

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
18
Sven Hohenstein

順序付けされていない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)をループすることでこれを自動化できます。

12
Jonas Lindeløv

私は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_)。

11
Gavin Simpson

このようなもの ?

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
4
juba

maxも機能します。文字列ベクトルでも機能します。

cbind(data[1], mycol=apply(data[-1], 1, max, na.rm=T))
1
drollix

関連リンク( paste()でNAを抑制する )でpasteのバージョンを_na.rm_オプション(不幸な名前の_paste5_)で提示します。

これにより、コードは

_cols <- c("x", "y", "z")
cbind.data.frame(a = data$a, mycol = paste2(data[, cols], na.rm = TRUE))
_

_paste5_の出力は文字です。これは、文字データがある場合に機能します。それ以外の場合は、必要な型に強制する必要があります。

0
JWilliman

これは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
0
Ferroao

dplyrtidyrを使用する1つの可能性は次のとおりです。

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を削除します。

0
tmfmnk