【问题标题】:unexpected output from aggregate聚合的意外输出
【发布时间】:2013-01-04 14:05:42
【问题描述】:

在用aggregate 尝试另一个问题here 时,我遇到了一个相当奇怪的结果。我不知道为什么,我想知道我所做的是否完全错误。

假设,我有一个这样的data.frame

df <- structure(list(V1 = c(1L, 2L, 1L, 2L, 3L, 1L), 
                     V2 = c(2L, 3L, 2L, 3L, 4L, 2L), 
                     V3 = c(3L, 4L, 3L, 4L, 5L, 3L), 
                     V4 = c(4L, 5L, 4L, 5L, 6L, 4L)), 
                  .Names = c("V1", "V2", "V3", "V4"), 
        row.names = c(NA, -6L), class = "data.frame")
> df
#   V1 V2 V3 V4
# 1  1  2  3  4
# 2  2  3  4  5
# 3  1  2  3  4
# 4  2  3  4  5
# 5  3  4  5  6
# 6  1  2  3  4

现在,如果我想输出带有唯一行data.frame,并在df 中显示它们的频率。对于这个例子,

#   V1 V2 V3 V4 x
# 1  1  2  3  4 3
# 2  2  3  4  5 2
# 3  3  4  5  6 1

我通过以下实验使用aggregate 获得了这个输出:

> aggregate(do.call(paste, df), by=df, print)

# [1] "1 2 3 4" "1 2 3 4" "1 2 3 4"
# [1] "2 3 4 5" "2 3 4 5"
# [1] "3 4 5 6"
#   V1 V2 V3 V4                         x
# 1  1  2  3  4 1 2 3 4, 1 2 3 4, 1 2 3 4
# 2  2  3  4  5          2 3 4 5, 2 3 4 5
# 3  3  4  5  6                   3 4 5 6

所以,这给了我粘贴的字符串。所以,如果我使用length 而不是print,它应该会给我这样的出现次数,这是我想要的结果,就是这样(如下所示)。

> aggregate(do.call(paste, df), by=df, length)
#   V1 V2 V3 V4 x
# 1  1  2  3  4 3
# 2  2  3  4  5 2
# 3  3  4  5  6 1

这似乎奏效了。但是,当data.frame 维度为 4*2500 时,data.frame 的输出为 1*2501 而不是 4*2501(所有行都是唯一的,因此频率为 1)。

> df <- as.data.frame(matrix(sample(1:3, 1e4, replace = TRUE), nrow=4))
> o <- aggregate(do.call(paste, df), by=df, length)
> dim(o)
# [1]    1 2501

我使用只有唯一行的较小 data.frames 进行了测试,它提供了正确的输出(例如更改 nrow=40)。但是,当矩阵的维度增加时,这似乎不起作用。我就是不知道出了什么问题!有什么想法吗?

【问题讨论】:

  • 可能是因为字符串太长,as.character 插入了换行符?
  • 是的,作为替代方案,您可以使用aggregate(rep(1, nrow(df)), df, FUN = length)
  • 这与 as.character() 无关,因为它的每个参数都是长度为 1 的向量。要查看这部分是否有效,只需执行do.call(paste, df[1:3, ])

标签: r aggregate


【解决方案1】:

这里的问题是aggregate.data.frame() 如何确定组。

aggregate.data.frame() 中有一个循环形成分组变量grp。在该循环中,grp 通过以下方式更改/更新:

grp <- grp * nlevels(ind) + (as.integer(ind) - 1L)

如果将 by 转换为因子,并且循环已经遍历了所有这些因子,那么在您的示例中,grp 最终会是:

Browse[2]> grp
[1] Inf Inf Inf Inf

本质上,循环更新将grp 的值推到了一个与Inf 无法区分的数字。

完成后,aggregate.data.frame() 稍后会这样做

y <- y[match(sort(unique(grp)), grp, 0L), , drop = FALSE]

这就是之前的问题现在表现出来的地方

dim(y[match(sort(unique(grp)), grp, 0L), , drop = FALSE])

因为

match(sort(unique(grp)), grp, 0L)

显然只返回1

> match(sort(unique(grp)), grp, 0L)
[1] 1

因为grp 只有一个唯一值。

【讨论】:

  • by 组成的组太多了。我不建议您这样做,但查看问题的另一种方法是形成聚合将对其起作用的子数据帧grp 没有转到Inflength(split(do.call(paste, df), df))警告这会消耗掉你所有的内存(在我的 4GB 笔记本电脑上,我很快就耗尽了交换空间)。
  • @Arun 是的,debugonce() 是你做这类事情的朋友。
猜你喜欢
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 2016-08-28
  • 2018-08-24
  • 2021-10-13
  • 2020-02-21
  • 2012-05-06
  • 2019-03-21
相关资源
最近更新 更多