我正在处理如下所示的数据集
Id Time Location
754005 13:19:00 HK564
754005 13:19:00 IE578
980278 19:51:00 AK177
980278 21:15:00 JB237
Id
列包含重复的值,Time
可以包含也可以不包含重复的值,而Location
列包含唯一的值。
我正在尝试根据以下逻辑对此Id
值唯一的数据集进行过滤:
1)如果该Id
的时间值相同,则保留该Id
的最后一行。换句话说,id 754005
被重复两次,次数相同,但是Location
不同,因此保留最后一行意味着保留该行
754005 13:19:00 IE578
2)如果该Id
的时间值不同,则保留该Id
的最新时间值的行。换句话说,ID 980278
具有两个不同的时间值19:51:00
,21:15:00
,为此ID保留时间为21:15:00
的行,因为这是最近的时间。>
最终数据集如下所示
Id Time Location
754005 13:19:00 IE578
980278 21:15:00 JB237
答案 0 :(得分:1)
这可以通过用Time
对数据集进行排序并选择每个组中的最后一个观察值来实现。使用data.table
,它将变成“单线”:
library(data.table)
setDT(DF)[order(Time), .SD[.N], by = Id]
Id Time Location 1: 754005 13:19:00 IE578 2: 980278 21:15:00 JB237
或者,tail()
函数可用于选择每个组中的最后一个观测值:
setDT(DF)[order(Time), tail(.SD, 1), by = Id]
与到目前为止发布的其他答案相比,此解决方案需要更少的代码行,尤其是digEmAll的data.table
代码。因此,我认为这值得详细说明:
setDT(DF)
通过引用强制DF
到data.table对象 ,即as.data.table(DF)
创建副本时不进行复制。order(Time)
按字典顺序订购Time
。无需出于排序目的将时间字符串转换为其他内容。在这里,Time
是一个因素,在读取数据集时,其级别按字典顺序进行了排序。help("order")
,所有未解决的联系将保留其原始顺序。因此,Id == 754005
的行顺序将不会更改。.SD
是每个组的行的子集。 .N
是每个组中的行数。因此,.SD[.N]
选择每个组的最后一行。 library(data.table)
DF <- fread("
Id Time Location
754005 13:19:00 HK564
754005 13:19:00 IE578
980278 19:51:00 AK177
980278 21:15:00 JB237",
data.table = FALSE, stringsAsFactors = TRUE)
DF
是一个data.frame,其中字符列变成了假设“最坏情况”的因素。
str(DF)
'data.frame': 4 obs. of 3 variables: $ Id : int 754005 754005 980278 980278 $ Time : Factor w/ 3 levels "13:19:00","19:51:00",..: 1 1 2 3 $ Location: Factor w/ 4 levels "AK177","HK564",..: 2 3 1 4
答案 1 :(得分:0)
我们可以<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
group_by
和Id
arrange
以Time
结尾的顺序,并使用desc
<从每个组中选择最后一行< / p>
slice
答案 2 :(得分:0)
使用基数R的可能方法:
# recreate your input
DF <- read.table(text=
'Id Time Location
754005 13:19:00 HK564
754005 13:19:00 IE578
980278 19:51:00 AK177
980278 21:15:00 JB237',header=TRUE)
# convert time strings to datetimes
dates <- strptime(DF$Time,format='%H:%M:%S',tz='GMT')
# get the desired rows
DF2 <-
DF[unique(
ave(seq_len(nrow(DF)),DF$Id,
FUN=function(i)i[order(dates[i],i,decreasing=TRUE)][1]
)
)
,]
# > DF2
# Id Time Location
# 2 754005 13:19:00 IE578
# 4 980278 21:15:00 JB237
或使用data.table
:
library(data.table)
# convert data.frame to data.table
DT <- as.data.table(DF)
# create column with time strings converted to ITime objects
DT[,TimeConverted := as.ITime(Time,format='%H:%M:%S')]
# group by Id and choose the right row
DT2 <- DT[,{.SD[order(TimeConverted,.I,decreasing=TRUE)[1]]},by=Id]
# remove TimeConverted column
DT2[,TimeConverted := NULL]
# > DT2
# Id Time Location
# 1: 754005 13:19:00 IE578
# 2: 980278 21:15:00 JB237