在任意长的对象列表上使用cbind

rty*_*yro 27 statistics bind join r do.call

我想通过使用cbind()将多个单独的对象连接在一起来找到创建data.frame的方法.例如,如果A,B,C和D都是相等长度的矢量,则可以创建data.frameABCD

ABCD <- cbind(A,B,C,D)
Run Code Online (Sandbox Code Playgroud)

但是,当要组合的对象数量变大时,输入所有名称变得冗长乏味.此外,有没有办法调用cbind()对象名称的向量,例如

objs <- c("A", "B", "C", "D")
ABCD <- cbind(objs)
Run Code Online (Sandbox Code Playgroud)

或者在包含要组合的所有对象的列表上,例如

obj.list <- list(A,B,C,D)
ABCD <- cbind(obj.list)
Run Code Online (Sandbox Code Playgroud)

目前,我能想到的唯一解决方法是使用paste(),cat(),write.table(),和source()构建参数cbind(),写一个脚本和源吧.这似乎是一个非常讨厌的kludge.此外,我已经调查do.call()但似乎无法找到一种方法来实现我想要的东西.

Pra*_*ani 32

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
Run Code Online (Sandbox Code Playgroud)


Aar*_*ica 8

首先,您需要所需get的对象并将它们作为列表存储在一起; 如果您可以将其名称构造为字符串,则使用该get函数.这里我创建了两个变量,A并且B:

> A <- 1:4
> B <- rep(LETTERS[1:2],2)
Run Code Online (Sandbox Code Playgroud)

然后我构造一个包含其名称(存储为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"
Run Code Online (Sandbox Code Playgroud)

然后你可以使用do.call; 第一个参数是您想要的函数,第二个参数是一个包含您想要传递给它的参数的列表.

> do.call(cbind, obj.list)
     A   B  
[1,] "1" "A"
[2,] "2" "B"
[3,] "3" "A"
[4,] "4" "B"
Run Code Online (Sandbox Code Playgroud)

但是,正如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
Run Code Online (Sandbox Code Playgroud)