【问题标题】:Finding Unique per group with filter使用过滤器查找每个组的唯一值
【发布时间】:2018-03-05 04:34:50
【问题描述】:

我的数据如下所示:

   date schedule_id food_truck_id building_id   truck_status last_confirmed_date dsle
 2018-04-26         422            58          30 accepted_event                   0   31
 2018-04-26         422            59          30 accepted_event          2018-02-27   11
 2018-04-26         422            65          30 accepted_event          2018-03-15   12
 2018-04-26         422            88          30 accepted_event          2018-02-20    7
 2018-04-26         422            89          30 accepted_event          2018-03-22   13
 2018-04-26         422           101          30 accepted_event          2018-02-06   16
 2018-04-26         422           120          30 accepted_event          2018-03-06   14
 2018-04-26         422           135          30 accepted_event          2018-03-13   21
 2018-04-26         399            42          33 accepted_event          2018-03-15    8
 2018-04-26         399            58          33 accepted_event                   0   31
 2018-04-26         399            59          33 accepted_event          2018-03-01   11
 2018-04-26         399            65          33 accepted_event          2018-02-27   12
 2018-04-26         399            88          33 accepted_event                   

可以使用以下方法复制:

structure(list(date = structure(c(17647, 17647, 17647, 17647, 
17647, 17647, 17647, 17647, 17647, 17647, 17647, 17647, 17647, 
17647, 17647, 17647, 17647), class = "Date"), schedule_id = c(422L, 
422L, 422L, 422L, 422L, 422L, 422L, 422L, 399L, 399L, 399L, 399L, 
399L, 399L, 399L, 399L, 399L), food_truck_id = c(58L, 59L, 65L, 
88L, 89L, 101L, 120L, 135L, 42L, 58L, 59L, 65L, 88L, 89L, 101L, 
120L, 135L), building_id = c(30L, 30L, 30L, 30L, 30L, 30L, 30L, 
30L, 33L, 33L, 33L, 33L, 33L, 33L, 33L, 33L, 33L), truck_status = c("accepted_event", 
"accepted_event", "accepted_event", "accepted_event", "accepted_event", 
"accepted_event", "accepted_event", "accepted_event", "accepted_event", 
"accepted_event", "accepted_event", "accepted_event", "accepted_event", 
"accepted_event", "accepted_event", "accepted_event", "accepted_event"
), last_confirmed_date = c("0", "2018-02-27", "2018-03-15", "2018-02-20", 
"2018-03-22", "2018-02-06", "2018-03-06", "2018-03-13", "2018-03-15", 
"0", "2018-03-01", "2018-02-27", "0", "2018-03-06", "2018-03-13", 
"0", "2018-02-22"), dsle = c(31, 11, 12, 7, 13, 16, 14, 21, 8, 
31, 11, 12, 7, 13, 16, 14, 21)), .Names = c("date", "schedule_id", 
"food_truck_id", "building_id", "truck_status", "last_confirmed_date", 
"dsle"), row.names = c(142L, 223L, 379L, 455L, 495L, 589L, 806L, 
877L, 63L, 155L, 215L, 287L, 452L, 483L, 667L, 809L, 894L), class = "data.frame")

我的目标是仅根据 max(dsle) 选择 food_truck_id,但每个日期应该是唯一的。比如schedule_id 422,food_truck_id max(dsle) 是58,schedule_id 399 也是58。

我想要的是,假设 422 是 58,但对于 399,它应该是 58 以外的下一个 max(dsle)。

我尝试了以下方法,但它没有给出我想要的。

testxx %>% 
  group_by(schedule_id) %>% 
  distinct(food_truck_id, date, dsle) %>% 
  filter(dsle == max(dsle))

我想要的结果如下

date         schedule_id        food_truck_id    
2018-04-26     422                   58
2018-04-26     399                   135

因为 58 旁边的 135 有 max(dsle)

【问题讨论】:

  • 对于schedule_id 399,是您返回food_truck_id = 135 的原因,因为您已经为其他计划返回了food_truck_id 58,因此您不能返回相同的@ 987654328@两次?
  • @SymbolixAU 没错。这就是为什么我每天都提到独特的 food_truck_id。也因为 135 是 58 之后的第二个 max(dsle)
  • @alistaire 卡车应按 schedule_id 分组,因为每个 schedule_id 在同一天(日期)必须具有唯一的卡车 ID
  • 好的,所以您希望将重复的最大值设置为它们所属的组,以使最大值的总和最大化?这并不容易。
  • @mt1022 这意味着整个 schedule_id 已经消失了。

标签: r dplyr data.table plyr


【解决方案1】:

更新到帐户日期

这可能是循环是最佳/最简单解决方案的情况之一。

但是,它在循环中做了一个连接操作,所以会有一些优化可以做

这个想法是循环遍历每个schedule_id,并跟踪哪个food_trucks 在哪个日期已经被使用过。

如果我们在循环之前对数据进行一些预先安排,这会让事情变得更容易

df <- df %>%
    arrange(schedule_id, -dsle)

## pre-allocate a result data.frame
ids <- unique(df$schedule_id)
df_res <- data.frame(schedule_id = ids,
                food_truck_id = NA)

usedTrucks <- data.frame(date = as.Date(NA), 
                schedule_id = ids, 
                food_truck_id = NA_integer_)
counter <- 1

for(i in ids) {

    possibleTrucks <- df[df$schedule_id %in% i, c("date", "food_truck_id")]
    ## possible Trucks will be in order, as we have pre-arranged the data

    ## use the first one that hasn't already been used
    ## on the given date
    possibleTrucks <- anti_join(possibleTrucks, usedTrucks, by = c("date", "food_truck_id"))
    thisTruck <- possibleTrucks[1, c("food_truck_id", "date")]

    df_res[counter, 'food_truck_id'] <- thisTruck$food_truck_id

    usedTrucks[counter, "food_truck_id"] <- thisTruck$food_truck_id
    usedTrucks[counter, "date"] <- thisTruck$date

    counter <- counter + 1
}

df_res
#   schedule_id food_truck_id
# 1         399            58
# 2         422           135

如果速度是较大数据集的问题,则可以在Rcpp 中重写以使其更快。

【讨论】:

  • 感谢您的回答,遇到与上述相同的问题,当 schedule_ids 大于 2 时,它会在同一日期重复同一辆卡车。您认为如果我共享大型数据集,即仅 960 obs,您可以稍微调整一下吗?
  • 感谢您的回答,因为它会跟踪以前使用的卡车 ID,因此在更大的数据集上,我得到了很多 NA。相反,我想按日期跟踪卡车 ID,以便在同一日期不会为两个 schedule_id 选择相同的卡车 ID。
【解决方案2】:
p<-df %>% arrange(desc(schedule_id), desc(dsle)) %>% slice(1) %>% select(date,dsle,schedule_id,food_truck_id) 

df %>% subset(!(schedule_id%in%c(p))) %>% subset(!(dsle%in%c(p))) %>% select(date,dsle,schedule_id,food_truck_id) %>% arrange(desc(dsle)) %>% slice(1) %>% 
  rbind(p,.) %>% select(-dsle)

输出

# A tibble: 2 x 3
  date       schedule_id food_truck_id
  <date>           <int>         <int>
1 2018-04-26         422            58
2 2018-04-26         399           135

【讨论】:

  • 嗨 vsb,感谢您的回复,这是普通的 dplyr 对吗?我正在尝试在我的数据上运行它,但我只得到 1 个 obs。
  • 是的,这是普通的 dplyr。我的 dplyr 版本是“0.7.4”
  • 嗨 vsb,感谢您的回复,出于某种原因,我得到了 schedule_id 的欺骗,两个 schedule_ids 的 58 与 food_truck_id 相同
  • 这在我上面给出的大量数据中非常有效!但是,可能需要进行一些调整才能使其扩展到我的整个数据。
  • 如果我分享我的数据,您认为您可以查看吗?它只有 960 obs。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多