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]
_を使用して列を呼び出すことができます。
任意の助けをいただければ幸いです。
ありがとう
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
を使用して、列を1つのベクトルに変換できます。その後、na.omit
を使用してNA
sを削除できます。
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
順序付けされていない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)
をループすることでこれを自動化できます。
私は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
_)。
このようなもの ?
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を抑制する )でpaste
のバージョンを_na.rm
_オプション(不幸な名前の_paste5
_)で提示します。
これにより、コードは
_cols <- c("x", "y", "z")
cbind.data.frame(a = data$a, mycol = paste2(data[, cols], na.rm = TRUE))
_
_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
を使用する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を削除します。