web-dev-qa-db-ja.com

オブジェクトの任意の長いリストでのcbindの使用

cbind()を使用してdata.frameを作成し、多くの個別のオブジェクトを結合する方法を見つけたいと思います。たとえば、A、B、C、Dがすべて同じ長さのベクトルである場合、data.frame ABCDを作成できます。

ABCD <- cbind(A,B,C,D)

ただし、組み合わせるオブジェクトの数が多くなると、すべての名前を入力するのが面倒になります。さらに、オブジェクト名のベクトルでcbind()を呼び出す方法はありますか。

objs <- c("A", "B", "C", "D")
ABCD <- cbind(objs)

または、結合するすべてのオブジェクトを含むリスト。

obj.list <- list(A,B,C,D)
ABCD <- cbind(obj.list)

現在、考えられる唯一の回避策は、paste()cat()write.table()、およびsource()を使用してcbind()への引数を作成することです。 ]、それをスクリプトとして記述し、ソースにします。これは非常に厄介なクラッジのようです。また、do.call()を調査しましたが、それを使ってやりたいことを達成する方法を見つけることができません。

28
rtyro

do.call関数はここで非常に便利です。

A <- 1:10
B <- 11:20
C <- 20:11

> do.call(cbind, list(A,B,C))
      [,1] [,2] [,3]
 [1,]    1   11   20
 [2,]    2   12   19
 [3,]    3   13   18
 [4,]    4   14   17
 [5,]    5   15   16
 [6,]    6   16   15
 [7,]    7   17   14
 [8,]    8   18   13
 [9,]    9   19   12
[10,]   10   20   11
31

最初に、必要なオブジェクトをgetして、それらをリストとして一緒に格納する必要があります。名前を文字列として構成できる場合は、get関数を使用します。ここでは、2つの変数ABを作成します。

> A <- 1:4
> B <- rep(LETTERS[1:2],2)

次に、nsを使用して、それらの名前(getとして保存)とlapplyを含む文字ベクトルを作成します。次に、リストの名前を元の名前と同じに設定しました。

> (ns <- LETTERS[1:2])
[1] "A" "B"
> obj.list <- lapply(ns, get)
> names(obj.list) <- ns
> obj.list
$A
[1] 1 2 3 4

$B
[1] "A" "B" "A" "B"

その後、do.callを使用できます。最初の引数は必要な関数で、2番目は渡したい引数のリストです。

> do.call(cbind, obj.list)
     A   B  
[1,] "1" "A"
[2,] "2" "B"
[3,] "3" "A"
[4,] "4" "B"

ただし、aL3xaが正しく注記しているように、これによりデータフレームではなく行列が作成されます。変数が異なるクラスの場合、これは必要なものではない可能性があります。ここで、私のAは、数値ベクトルではなく文字ベクトルに強制変換されています。リストからデータフレームを作成するには、その上でdata.frameを呼び出すだけです。その後、変数のクラスが保持されます。

> (AB <- data.frame(obj.list))
  A B
1 1 A
2 2 B
3 3 A
4 4 B
> sapply(AB, class)
        A         B 
"integer"  "factor" 
> str(AB)
'data.frame':   4 obs. of  2 variables:
 $ A: int  1 2 3 4
 $ B: Factor w/ 2 levels "A","B": 1 2 1 2
8
Aaron

ただし、cbindがアトミックベクトル(この場合はdouble)のみに適用されると、アトミックベクトル(行列)を返すことに注意してください。 @prasadと@Aaronの回答でわかるように、結果のオブジェクトは行列です。他のアトミックベクトル(整数、倍精度、論理、複素数)を文字ベクトルと共に指定すると、それらは文字に強制変換されます。そして、あなたには問題があります-あなたはそれらを望ましいクラスに変換しなければなりません。そう、

a、B、C、Dがすべて同じ長さのベクトルの場合、data.frame ABCDを作成できます

ABCD <- data.frame(A, B, C, D)

多分あなたは尋ねるべきです"等しい長さの様々なベクトルをどのように簡単に集め、それらをdata.frame "?cbindは素晴らしいですが、探しているものと異なる場合があります...

3
aL3xa

環境内のすべてのベクトルをeapplyを使用してリストに配置できます。

obj.list <- eapply(.GlobalEnv,function(x) if(is.vector(x)) x)
obj.list <- obj.list[names(obj.list) %in% LETTERS]
1
Wojciech Sobala