web-dev-qa-db-ja.com

異なる長さのベクトルの結合(cbind)

異なる長さのベクターがいくつかあり、cbindしたいです。ベクターをリストに入れて、do.call(cbind, ...)を使用して結合しようとしました:

nm <- list(1:8, 3:8, 1:5)
do.call(cbind, nm)

#      [,1] [,2] [,3]
# [1,]    1    3    1
# [2,]    2    4    2
# [3,]    3    5    3
# [4,]    4    6    4
# [5,]    5    7    5
# [6,]    6    8    1
# [7,]    7    3    2
# [8,]    8    4    3
# Warning message:
#   In (function (..., deparse.level = 1)  :
#         number of rows of result is not a multiple of vector length (arg 2)

予想どおり、結果の行列の行数は最長のベクトルの長さであり、短いベクトルの値は長さを補うためにリサイクルされます。

代わりに、最も短いベクトルにNA値を埋め込み、最も長いベクトルと同じ長さにします。マトリックスを次のようにしたいです。

#      [,1] [,2] [,3]
# [1,]    1    3    1
# [2,]    2    4    2
# [3,]    3    5    3
# [4,]    4    6    4
# [5,]    5    7    5
# [6,]    6    8    NA
# [7,]    7    NA   NA
# [8,]    8    NA   NA

どうすればこれを行うことができますか?

30
Nick

インデックスを使用できます。オブジェクトのサイズを超える数値をインデックス化すると、NAが返されます。これは、fooで定義された任意の行数で機能します。

_nm <- list(1:8,3:8,1:5)

foo <- 8

sapply(nm, '[', 1:foo)
_

編集:

または、最大ベクトルを行数として使用する1行で:

_sapply(nm, '[', seq(max(sapply(nm,length))))
_

_R 3.2.0_から、sapply(nm, length)の代わりにlengths(「リストの各要素の長さを取得」)を使用できます。

_sapply(nm, '[', seq(max(lengths(nm))))
_
30
Sacha Epskamp

Do.callを呼び出す前に、ベクターにNAを入力する必要があります。

nm <- list(1:8,3:8,1:5)

max_length <- max(unlist(lapply(nm,length)))
nm_filled <- lapply(nm,function(x) {ans <- rep(NA,length=max_length);
                                    ans[1:length(x)]<- x;
                                    return(ans)})
do.call(cbind,nm_filled)
5
Wojciech Sobala

これはWojciechのソリューションの短縮バージョンです。

nm <- list(1:8,3:8,1:5)
max_length <- max(sapply(nm,length))
sapply(nm, function(x){
    c(x, rep(NA, max_length - length(x)))
})
3
Thierry

パーティーに遅れましたが、cbind.fill from rowrパッケージのfill = NA

library(rowr)
do.call(cbind.fill, c(nm, fill = NA))

#  object object object
#1      1      3      1
#2      2      4      2
#3      3      5      3
#4      4      6      4
#5      5      7      5
#6      6      8     NA
#7      7     NA     NA
#8      8     NA     NA

名前付きのlistが代わりにあり、ヘッダーを維持したい場合は、setNamesを使用できます。

nm <- list(a = 1:8, b = 3:8, c = 1:5)
setNames(do.call(cbind.fill, c(nm, fill = NA)), names(nm))

#  a  b  c
#1 1  3  1
#2 2  4  2
#3 3  5  3
#4 4  6  4
#5 5  7  5
#6 6  8 NA
#7 7 NA NA
#8 8 NA NA
2
Ronak Shah

stringiからstri_list2matrixを使用するオプションは次のとおりです。

library(stringi)
out <- stri_list2matrix(nm)
class(out) <- 'numeric'
out
#      [,1] [,2] [,3]
#[1,]    1    3    1
#[2,]    2    4    2
#[3,]    3    5    3
#[4,]    4    6    4
#[5,]    5    7    5
#[6,]    6    8   NA
#[7,]    7   NA   NA
#[8,]    8   NA   NA
1
akrun