【问题标题】:Most efficient to append some columns of a data frame to some other columns将数据框的某些列附加到其他一些列最有效
【发布时间】:2016-07-18 20:05:46
【问题描述】:

假设我有以下数据框:

foo <- data.frame(a=letters,b=seq(1,26),
                  n1=rnorm(26),n2=rnorm(26),
                  u1=runif(26),u2=runif(26))

我想将列 u1u2 附加到列 n1n2。目前,我找到了以下方法:

df1 <- foo[,c("a","b","n1","n2")]
df2 <- foo[,c("a","b","u1","u2")]
names(df2) <- names(df1)
bar <- rbind(df1,df2) 

这就是诀窍。但是,它似乎有点涉及。我是不是太挑剔了?或者在 R 中有更快/更简单的方法吗?

【问题讨论】:

  • 你可能会通过搜索重塑而不是附加reshape(foo, dir = 'long', varying = list(c('n1','u1'), c('n2','u2')))[,c("a","b","n1","n2")]来找到你需要的东西
  • 也许吧? rbind(foo[1:4], setNames(foo[c(1, 2, 5, 6)], names(foo[1:4])))
  • @rawr,我更喜欢您的解决方案,因为它使用命名列而不是数字,因此它会产生更具可读性的代码。我尝试阅读?reshape,这是我对您的代码的理解:如果需要,请更正/整合,以便我学习。varying 存储必须连接的列对。所有其他列都是重复的。由于reshape 的结果还包含重复的u1u2 列,我不需要这些列,因此您只需使用[,c("a","b","n1","n2")] 过滤所需的列。对吗?
  • @DeltaIV varying 列将从宽格式重新调整为长格式。所有其他列都假定为 id 变量,这意味着它们将保持不变并根据需要进行复制以匹配从宽到长的尺寸。 reshape 添加一些额外的列,这些列对于将结果转换回原始格式很有用,但由于这里不需要它们,我们就忽略它们
  • @rawr,您的解决方案是我最喜欢的解决方案。如果您将其发布为答案,我会选择它。

标签: r dataframe append


【解决方案1】:

使用Map() 连接列,并使用cbind() 循环以到达最终数据帧。

cbind(foo[1:2], Map(c, foo[3:4], foo[5:6]))

如果需要,用列名替换数字索引。

cbind(foo[c("a", "b")], Map(c, foo[c("n1", "n2")], foo[c("u1", "u2")]))

【讨论】:

    【解决方案2】:

    速记:

    rbind(foo[1:4], setNames(foo[c(1, 2, 5, 6)], names(foo[1:4])))
    

    啰嗦:

    rbind(foo[c("a", "b", "n1", "n2")], setNames(foo[c("a", "b", "u1", "u2")], c("a", "b", "n1", "n2")))
    

    啰嗦(更干):

    nms <- c("a", "b", "n1", "n2")
    rbind(foo[nms], setNames(foo[c("a", "b", "u1", "u2")], nms))
    

    【讨论】:

    • 我更喜欢 DRY 解决方案,因为它的可读性。我很惊讶foo[nms] 有效。我一直认为正确的电话是foo[ ,nms]。看来我一直都错了。
    【解决方案3】:

    这是使用来自dplyrfull_join() 的一种方式:

    library(dplyr)
    full_join(df1, df2, by = c("a", "b", "n1" = "u1", "n2" = "u2"))
    

    来自文档:

    full_join

    返回 x 和 y 的所有行和所有列。在哪里 没有匹配的值,为缺少的返回 NA。

    要连接的变量的字符向量。如果为 NULL,则默认值, join 将使用所有具有通用名称的变量进行自然连接 横跨两张桌子。一条消息列出了变量,以便您可以 检查他们是否正确。

    要通过 x 和 y 上的不同变量连接,请使用命名向量。为了 例如,by = c("a" = "b") 将匹配 x.a 到 y.b。

    【讨论】:

    • @Steven Beaupré,这是一个有趣的选项,但它需要预先将 foo 拆分为 df1df2。这不是一件坏事——这就是我现在所做的! - 但其他解决方案不需要这个,因此我选择其中一个。
    • 嗯,也许创建df1df2 不是绝对必要的——可以简单地用foo[,c("a", "b", "n1", "n2")]foo[,c("a", "b", "u1", "u2")] 替换它们,以牺牲可读性。尽管如此,reshape 解决方案对我来说似乎更具可读性,但这可能只是个人喜好问题。
    • @DeltaIV 你也可以这样做:full_join(select(foo, -starts_with("u")), select(foo, -starts_with("n")), by = c("a", "b", "n1" = "u1", "n2" = "u2"))
    猜你喜欢
    • 2020-05-05
    • 2022-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-13
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    相关资源
    最近更新 更多