mat*_*lin 13 filtering r dataframe
我有一个180,000 x 400的数据框,其中行对应于用户,但每个用户只有两行.
id date ...
1 2012 ...
3 2010 ...
2 2013 ...
2 2014 ...
1 2011 ...
3 2014 ...
Run Code Online (Sandbox Code Playgroud)
我希望对数据进行子集化,以便仅保留每个用户的最新行(即每个id的日期值最高的行).
我首先尝试使用which()
循环语句,其中ids
的ifelse()
语句sapply()
很慢(O(n^2)
我相信).
然后我尝试对df
by进行排序id
,然后以2的增量循环并比较相邻的日期,但这也很慢(我想因为R中的循环是没有希望的).这两个日期的比较是瓶颈,因为排序几乎是即时的.
有没有办法对比较进行矢量化?
解决方案来自删除重复项,保持最大绝对值的输入
aa <- df[order(df$id, -df$date), ] #sort by id and reverse of date
aa[!duplicated(aa$id),]
Run Code Online (Sandbox Code Playgroud)
跑得很快!!
Dav*_*urg 25
这是一个使用data.table包的简单快速的方法
library(data.table)
setDT(df)[, .SD[which.max(date)], id]
# id date
# 1: 1 2012
# 2: 3 2014
# 3: 2 2014
Run Code Online (Sandbox Code Playgroud)
或者(由于键控可能会更快一点 by
setkey(setDT(df), id)[, .SD[which.max(date)], id]
Run Code Online (Sandbox Code Playgroud)
或者通过data.table
包使用OPs的想法
unique(setorder(setDT(df), id, -date), by = "id")
Run Code Online (Sandbox Code Playgroud)
要么
setorder(setDT(df), id, -date)[!duplicated(id)]
Run Code Online (Sandbox Code Playgroud)
或者基础R解决方案
with(df, tapply(date, id, function(x) x[which.max(x)]))
## 1 2 3
## 2012 2014 2014
Run Code Online (Sandbox Code Playgroud)
其他方式
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
Run Code Online (Sandbox Code Playgroud)
要么
df %>%
group_by(id) %>%
slice(which.max(date)) # Will keep all columns but won't return multiple rows in case of ties
Run Code Online (Sandbox Code Playgroud)
要么
df %>%
group_by(id) %>%
summarise(max(date)) # Will remove all other columns and wont return multiple rows in case of ties
Run Code Online (Sandbox Code Playgroud)
聚合也应该有效:
aggregate(date ~ id, df, max)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7235 次 |
最近记录: |