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

发布于 2024-10-29 16:20:49 字数 674 浏览 3 评论 0原文

我想找到一种通过使用 cbind() 将许多单独的对象连接在一起来创建 data.frame 的方法。例如,如果A、B、C& D 都是等长的向量,可以用 ABCD 创建 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() 但似乎找不到一种方法来完成我想要的事情。

I would like to find a way to create a data.frame by using cbind() to join together many separate objects. For example, if A, B, C & D are all vectors of equal length, one can create data.frame ABCD with

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

However, when the number of objects to be combined gets large, it becomes tedious to type out all of their names. Furthermore, Is there a way to call cbind() on a vector of object names, e.g.

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

or on a list containing all the objects to be combined, e.g.

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

Currently, the only workaround I can think of is to use paste(), cat(), write.table(), and source() to construct the arguments to cbind(), write it as a script and source it. This seems like a very nasty kludge. Also, I have looked into do.call() but can't seem to find a way to accomplish what I want with it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蓝咒 2024-11-05 16:21:10

不过,您应该记住,当仅应用于原子向量时,cbind 将返回一个原子向量(矩阵)(在本例中为 double)。正如您在@prasad 和@Aaron 的答案中看到的,结果对象是一个矩阵。如果您指定其他原子向量(整数、双精度、逻辑、复数)以及字符向量,它们将被强制转换为字符。然后你遇到一个问题 - 你必须将它们转换为所需的类。所以,

如果 A、B、C 和D 都是向量
长度相等,可以创建
data.frame ABCD 与

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

也许你应该问“我如何轻松收集相同长度的各种向量并将它们放入 data.frame”? cbind 很棒,但有时它不是您要找的......

You should bare in mind, though, that cbind will return an atomic vector (matrix) when applied solely on atomic vectors (double in this case). As you can see in @prasad's and @Aaron's answers, resulting object is a matrix. If you specify other atomic vectors (integer, double, logical, complex) along with character vector, they will get coerced to character. And then you have a problem - you have to convert them to desired classes. So,

if A, B, C & D are all vectors of
equal length, one can create
data.frame ABCD with

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

Perhaps you should ask "how can I easily gather various vectors of equal length and put them in a data.frame"? cbind is great, but sometimes it's not what you're looking for...

逐鹿 2024-11-05 16:21:10

您可以使用 eapply 将环境中的所有向量放入列表中。

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

You can put all vectors in environment into list using eapply.

obj.list <- eapply(.GlobalEnv,function(x) if(is.vector(x)) x)
obj.list <- obj.list[names(obj.list) %in% LETTERS]
同尘 2024-11-05 16:21:09

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

The do.call function is very useful here:

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
抠脚大汉 2024-11-05 16:21:09

首先,您需要获取您想要的对象并将它们存储在一起作为列表;如果您可以将它们的名称构造为字符串,则可以使用 get 函数。在这里,我创建了两个变量,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;第一个参数是您想要的函数,第二个参数是包含您想要传递给它的参数的列表。

> 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

First you need to get the objects you want and store them together as a list; if you can construct their names as strings, you use the get function. Here I create two variables, A and B:

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

I then construct a character vector containing their names (stored as ns) and get these variables using lapply. I then set the names of the list to be the same as their original names.

> (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"

Then you can use do.call; the first argument is the function you want and the second is a list with the arguments you want to pass to it.

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

However, as aL3xa correctly notes, this makes a matrix, not a data frame, which may not be what you want if the variables are different classes; here my A has been coerced to a character vector instead of a numeric vector. To make a data frame from a list, you just call data.frame on it; then the classes of the variables are retained.

> (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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文