2013-01-21 55 views
10

aggregatehere的另一个问题进行实验时,我遇到了一个相当奇怪的结果。我无法弄清楚为什么,想知道我在做什么是完全错误的。集合的意外输出

想,我有一个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)。

​​

我与只是唯一行较小data.frames测试,它使右输出(变化nrow=40,例如)。但是,当矩阵的尺寸增加时,这似乎不起作用。我只是无法弄清楚发生了什么问题!有任何想法吗?

+2

也许,因为字符串变得太长而'as.character'插入换行符? – Roland

+0

是的,作为一种替代方法,您可以执行'aggregate(rep(1,nrow(df)),df,FUN = length)'。 – flodel

+1

这与'as.character()'无关,因为它的每个参数都是长度为1的向量。要看到这部分工作,只需执行'do.call(paste,df [1:3,])'。 –

回答

10

这里的问题是如何确定组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

+1

只有'by'形成了太多的群体。我不建议你这样做,但另一种看待问题的方式是形成聚合的子数据帧,它可以处理'grp'没有去'Inf':'length(split(do.call (paste,df),df))'。 **警告**,这将消耗您的所有内存(在我的4GB笔记本电脑上,我很快就会崩溃交换空间)。 –

+1

@阿伦是的,''''''''''''''''debugonce()'是你这种事情的朋友。 –