R根据二级现场条件获取数据框的唯一记录

时间:2012-12-15 08:35:02

标签: r

更新和简化

我有一个非常大的表(约700万条记录),它具有以下结构。

temp <- read.table(header = TRUE, stringsAsFactors=FALSE,
                   text = "Website Datetime    Rating
A 2007-12-06T14:53:07Z        1
A 2006-07-28T03:52:26Z        4
B 2006-11-02T11:06:25Z        2
C 2007-06-19T06:56:08Z        5
C 2009-11-28T22:27:58Z        2
C 2009-11-28T22:28:13Z        2")

我想要检索的是每个网站具有最高评级的唯一网站:

Website    Rating
A    4
B    2
C    5

我尝试使用for循环,但速度太慢了。还有其他方法可以达到这个目的。

2 个答案:

答案 0 :(得分:3)

 do.call( rbind, lapply( split(temp, temp$Website) , 
                               function(d) d[ which.max(d$Rating), ] ) )
  Website             Datetime Rating
A       A 2006-07-28T03:52:26Z      4
B       B 2006-11-02T11:06:25Z      2
C       C 2007-06-19T06:56:08Z      5

由于您的日期时间&#39;变量实际上似乎不是Date或datetime对象,您应该首先转换为Date对象。

which.max将选择最大的第一个项目。

>  which.max(c(1,1,2,2))
[1] 3

因此,阿南达在这方面的警告可能不正确。如果机器内存适中,数据表方法肯定会更快,也可能成功。上面的方法可以在此过程中制作多个副本,data.table函数不需要复制那么多。

答案 1 :(得分:2)

我可能会探索data.table包,但没有更多细节,以下示例解决方案很可能 < em>将成为你需要的东西。我之所以提到这一点是因为,特别是每组可能有多个匹配max的“评级”记录;你想怎么处理这些案件?

library(data.table)
temp <- read.table(header = TRUE, stringsAsFactors=FALSE,
                text = "Website Datetime    Rating
                        A       2012-10-9   10
                        A       2012-11-10  12
                        B       2011-10-9   5")
DT <- data.table(temp, key="Website")
DT
#    Website   Datetime Rating
# 1:       A  2012-10-9     10
# 2:       A 2012-11-10     12
# 3:       B  2011-10-9      5
DT[, list(Datetime = Datetime[which.max(Rating)], 
          Rating = max(Rating)), by = key(DT)]
#    Website   Datetime Rating
# 1:       A 2012-11-10     12
# 2:       B  2011-10-9      5

我建议您获取更好的答案,您可能希望包含一些信息,例如您的日期时间变量可能会如何影响您的汇总,或者是否可能存在多个“最大” “每组的价值。

如果您想要所有与max匹配的行,则修复很简单:

DT[, list(Time = Times[Rating == max(Rating)], 
          Rating = max(Rating)), by = key(DT)]

如果您只想要Rating列,则有许多方法可以解决此问题。按照上述相同步骤转换为data.table,请尝试:

DT[, list(Datetime = max(Rating)), by = key(DT)]
     Website Datetime
# 1:       A        4
# 2:       B        2
# 3:       C        5

或者,保持原始的“临时”data.frame,尝试aggregate()

aggregate(Rating ~ Website, temp, max)
    Website Rating
# 1       A      4
# 2       B      2
# 3       C      5

另一种方法,使用ave

temp[with(temp, Rating == ave(Rating, Website, FUN=max)), ]