【问题标题】:Using cbind on an arbitrarily long list of objects在任意长的对象列表上使用 cbind
【发布时间】:2021-02-01 03:25:36
【问题描述】:

我想找到一种方法来创建一个 data.frame 使用cbind() 将许多单独的对象连接在一起。例如,如果 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(),但似乎无法找到一种方法来完成我想要的。

【问题讨论】:

  • Reduce(cbind, obj.list) 除了@prasad-chalasani 的回答外,也可以使用。

标签: r join statistics bind do.call


【解决方案1】:

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

【讨论】:

  • 随着数据框大小的增长,这变得非常低效
【解决方案2】:

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

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

然后,我使用lapply 构造一个包含它们的名称(存储为ns)和get 这些变量的字符向量。然后我将列表的名称设置为与其原始名称相同。

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

【讨论】:

    【解决方案3】:

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

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

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

    也许你应该问“我怎样才能轻松地收集各种长度相等的向量并将它们放在 data.frame 中”? cbind 很棒,但有时它不是你想要的为...

    【讨论】:

    • 一种解决方案是使用 cbind.data.fram():do.call(cbind.data.frame, list)。看到这个线程:r.789695.n4.nabble.com/…
    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 2012-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-02
      • 2013-06-01
      • 1970-01-01
      • 2018-11-08
      相关资源
      最近更新 更多