【问题标题】:split a data.frame by columns using a grouping variable使用分组变量按列拆分 data.frame
【发布时间】:2011-08-12 23:16:41
【问题描述】:

根据分组因素将data.frame 按行拆分是相当容易的。但是如何按列拆分并可能应用函数?

my.df <- data.frame(a = runif(10),
        b = runif(10),
        c = runif(10),
        d = runif(10))
grp <- as.factor(c(1,1, 2,2))

我想要的是按组划分列的平均值。

到目前为止,我所拥有的只是一个穷人的申请。

lapply(as.list(as.numeric(levels(grp))), FUN = function(x, cn, data) {
            rowMeans(data[grp %in% x])
        }, cn = grp, data = my.df)

编辑 谢谢大家的参与。我运行了 10 次重复*,我的工作 data.frame 大约有 22000 行。这些是以秒为单位的结果。

Roman: 2.19
Joris: 4.60
Joris #2: 3.79 #changed sapply to lapply as suggested by Joris in the [R chatroom][1].
Gavin: 4.70
James & EDi: > 200 # * ran only one replicate due to the large order of magnitude difference

让我感到奇怪的是,手头的任务没有包装函数。也许有一天我们可以做到

apply(X = my.df, MARGIN = 3, INDEX = my.groups, FUN = mean) # :)

【问题讨论】:

  • 你的数据框有 10 行,grp 有 4 个值。他们应该如何匹配?
  • @hadley : 数据框有 4 列,grp 有 4 个值,所以匹配...
  • @hadley,我想按列而不是按行拆分,所以我应该匹配 length(my.df) == length(grp)。

标签: r split dataframe


【解决方案1】:

您可以使用相同的逻辑,但形式更方便:

sapply(levels(grp),function(x)rowMeans(my.df[which(grp==x)]))

【讨论】:

  • 那个版本比我给 Joris 看的那个版本快约 2 倍。索引通常是。 +1
【解决方案2】:

my.df 转换为列表并将其拆分,然后在强制转换为数据框后将您的函数应用于列表的每个组件子集:

lapply(split(as.list(my.df), grp), function(x) rowMeans(as.data.frame(x)))

这给出了:

> lapply(split(as.list(my.df), grp), function(x) rowMeans(as.data.frame(x)))
$`1`
 [1] 0.8229189 0.4901288 0.2057578 0.6531641 0.3897858 0.4225179
 [7] 0.3905410 0.3928784 0.1715857 0.3973192

$`2`
 [1] 0.61348623 0.61229702 0.31938521 0.28325342 0.25857158
 [6] 0.49071991 0.01179999 0.57639186 0.38407240 0.17467337

相当于@Roman的“穷人的申请”:

> roman <- lapply(as.list(as.numeric(levels(grp))), 
+                 FUN = function(x, cn, data) {
+                     rowMeans(data[grp %in% x])
+                 }, cn = grp, data = my.df)
> gavin <- lapply(split(as.list(my.df), grp), 
+                 function(x) rowMeans(as.data.frame(x)))
> all.equal(roman, gavin)
[1] "names for current but not for target"

组件上的名称除外。

【讨论】:

  • 这个方法默默地忽略了grp向量不是正确长度的事实。
  • @hadley 什么长度不合适? grp 的长度为 4,as.list(my.df) 的长度也为 4。为什么这不等同于 split(1:4, grp)?列表毕竟是一个向量。
  • @hadley 对 Q 发表了您的评论,我认为您误解了所要求的内容。
  • @hadley 没有问题 - 让我怀疑自己有一分钟!如果你的投票是反对票(如果是的话,不用担心),那么我最近的小修改应该允许你撤消,如果你愿意:-)
  • 我不明白为什么 stackoverflow 必须锁定你的投票 - 我通常需要 2 个多小时才能意识到我错了!
【解决方案3】:

这行得通吗?

aggregate(t(my.df), list(grp), mean)

【讨论】:

  • 这个方法默默地忽略了grp向量不是正确长度的事实。
【解决方案4】:

怎么样:

my.df2 <- data.frame(t(my.df),grp)
aggregate(.~grp,my.df2,mean)

【讨论】:

  • 抱歉,这个解决方案在我的工作数据集上花费了太多时间(请参阅我更新的答案)。
猜你喜欢
  • 1970-01-01
  • 2012-07-09
  • 2013-09-25
  • 2020-12-24
  • 1970-01-01
  • 2020-08-31
  • 2013-09-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多