按时间标准按ID子集数据集

时间:2018-08-20 01:26:51

标签: r subset

我正在处理如下所示的数据集

 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:0021:15:00,为此ID保留时间为21:15:00的行,因为这是最近的时间。

最终数据集如下所示

 Id           Time           Location
 754005       13:19:00       IE578
 980278       21:15:00       JB237

3 个答案:

答案 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]

说明

与到目前为止发布的其他答案相比,此解决方案需要更少的代码行,尤其是digEmAlldata.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_byId arrangeTime结尾的顺序,并使用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