【问题标题】:R Obtain unique records on data frame based on secondary field conditionsR 根据次要字段条件获取数据帧上的唯一记录
【发布时间】:2023-03-05 07:21:01
【问题描述】:

更新和简化

我有一个非常大的表(约 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 循环,但它太慢了。有没有其他方法可以实现这一点。

【问题讨论】:

  • 我会split 数据并使用lapply 浏览每个网站,应用您的标准。通过提供可重复的示例和预期结果来帮助我们节能人士。
  • 感谢罗曼!我更新了我的问题并使其更加具体。你能给我举个例子,说明如何将 split 与 lapply 结合以获得所需的结果?
  • 我认为@RomanLuštrik 提到的splitlapply 的想法与DWin 在他的回答中的观点一致。另外,请参阅我的答案的更新,以匹配满足您条件的 all 行。

标签: r


【解决方案1】:
 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

由于您的“日期时间”变量实际上还不是日期或日期时间对象,因此您可能应该首先转换为日期对象。

which.max 将选择第一个最大值。

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

因此,阿难达在这方面的警告可能不正确。数据表方法肯定会更快,如果机器内存适中,也可能成功。上面的方法可能会沿途进行多次复制,而data.table函数不需要复制那么多。

【讨论】:

  • DWin 永远不会正确地取我的名字.... :( ...虽然我知道 he 的名字也很难取对:)
【解决方案2】:

我可能会探索data.table 包,虽然没有更多细节,但以下示例解决方案最有可能 不是 会是你需要的。我提到这一点是因为,特别是,每个组可能有多个“评级”记录匹配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

我建议要获得更好的答案,您可能需要包含诸如日期时间变量如何影响您的聚合,或者是否可能存在多个“最大值”等信息" 每组的价值。

如果你想要 all 匹配最大值的行,修复很简单:

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

或者,保留原来的“temp”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)), ]

【讨论】:

  • 非常感谢您的帮助。每个类别可以有多个最大值。例如,A 网站示例中的评分可能都是 10。
  • @MichaelTsikerdekis,好的,然后呢?正如我所提到的,请使用更真实的数据样本更新您的问题,同时提及您希望遇到的瓶颈类型以及您希望如何处理它们。例如,如果有多个最大值,您是否希望 all 行匹配条件,或者匹配条件的 first 行是否足够(如which.max 会)。
  • 我刚刚更新了帖子并简化了问题。这可能应该更清楚,更容易解决。我试着自己做,但到目前为止失败得很惨。
  • @MichaelTsikerdekis,据我所知,我的原始答案仍然适用。你试过了吗?
  • 阿南达确实有效!非常感谢,也感谢 data.table 的想法。我以前从未使用过它,它似乎比 data.frame 更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-17
  • 2021-09-05
  • 2017-11-10
  • 2017-04-24
  • 1970-01-01
相关资源
最近更新 更多