我有一个180,000 x 400的数据框,其中行对应于用户,但每个用户只有两行。
id date ...
1 2012 ...
3 2010 ...
2 2013 ...
2 2014 ...
1 2011 ...
3 2014 ...
我希望对数据进行子集化,以便仅保留每个用户的最新行(即每个ID的日期值最高的行)。
我首先尝试在which()
中使用ids
循环ifelse()
和sapply()
语句,但速度非常缓慢(我相信O(n^2)
)。
然后我尝试按df
排序id
,然后以2为增量循环并比较相邻日期,但这也很慢(我猜因为R中的循环是没有希望的)。两个日期的比较是瓶颈,因为排序几乎是即时的。
有没有办法对比较进行矢量化?
来自Remove duplicates keeping entry with largest absolute value
的解决方案aa <- df[order(df$id, -df$date), ] #sort by id and reverse of date
aa[!duplicated(aa$id),]
跑得很快!!
答案 0 :(得分:22)
这是使用data.table包
的一种简单快捷的方法library(data.table)
setDT(df)[, .SD[which.max(date)], id]
# id date
# 1: 1 2012
# 2: 3 2014
# 3: 2 2014
或者(由于键入 by
setkey(setDT(df), id)[, .SD[which.max(date)], id]
或通过data.table
包
unique(setorder(setDT(df), id, -date), by = "id")
或者
setorder(setDT(df), id, -date)[!duplicated(id)]
或基础R解决方案
with(df, tapply(date, id, function(x) x[which.max(x)]))
## 1 2 3
## 2012 2014 2014
另一种方式
library(dplyr)
df %>%
group_by(id) %>%
filter(date == max(date)) # Will keep all existing columns but allow multiple rows in case of ties
# Source: local data table [3 x 2]
# Groups: id
#
# id date
# 1 1 2012
# 2 2 2014
# 3 3 2014
或者
df %>%
group_by(id) %>%
slice(which.max(date)) # Will keep all columns but won't return multiple rows in case of ties
或者
df %>%
group_by(id) %>%
summarise(max(date)) # Will remove all other columns and wont return multiple rows in case of ties
答案 1 :(得分:5)
聚合也应该有效:
aggregate(date ~ id, df, max)