[英]Remove past observations up to nearest observation to given date by group
雖然我已經實現了我想要的(見下面的結果),但我發現我的方法有點復雜。 我想按組刪除所有觀察結果,直到截止日期(此處為cut-off
日期)之前最近的觀察結果。 我不能簡單地使用min(abs(x - date))
計算最近的觀察值,因為在正面和負面中可能存在距離相等的觀察關系(例如mydf
中的“b”組)。
我通過查找date - cut_off <=0
的最后一次觀察的索引,然后在dplyr::slice()
中使用該索引來解決它。 不過,我對其他方法很好奇。
對於非 dplyr 解決方案非常開放。
每組至少包含一行observation date - cutoff date <= 0
library(tidyverse)
set.seed(8)
mydf <- data.frame(group = rep(letters[1:3], each = 5), date1 = as.Date(sample(15), origin = '1970-01-01'), cut_off = as.Date(rep(sample(10, 3), each = 5), origin = '1970-01-01'))
mydf %>% arrange(group, date1) %>% group_by(group) %>%
mutate(diff = date1 - cut_off,
min_abs = min(abs(date1 - cut_off)))
#> # A tibble: 15 x 5
#> # Groups: group [3]
#> group date1 cut_off diff min_abs
#> <fct> <date> <date> <drtn> <drtn>
#> 1 a 1970-01-03 1970-01-05 -2 days 0 days
#> 2 a 1970-01-05 1970-01-05 0 days 0 days
#> 3 a 1970-01-08 1970-01-05 3 days 0 days
#> 4 a 1970-01-13 1970-01-05 8 days 0 days
#> 5 a 1970-01-15 1970-01-05 10 days 0 days
#> 6 b 1970-01-02 1970-01-09 -7 days 2 days
#> 7 b 1970-01-06 1970-01-09 -3 days 2 days
#> 8 b 1970-01-07 1970-01-09 -2 days 2 days
#> 9 b 1970-01-11 1970-01-09 2 days 2 days
#> 10 b 1970-01-12 1970-01-09 3 days 2 days
#> 11 c 1970-01-04 1970-01-11 -7 days 1 days
#> 12 c 1970-01-09 1970-01-11 -2 days 1 days
#> 13 c 1970-01-10 1970-01-11 -1 days 1 days
#> 14 c 1970-01-14 1970-01-11 3 days 1 days
#> 15 c 1970-01-16 1970-01-11 5 days 1 days
# min(abs(x)) does not help when the distance from neg and pos values is tied, see group b
期望的結果(解決方案已經很好了)
mydf %>%
arrange(group, date1) %>%
group_by(group) %>%
mutate(diff = date1 - cut_off) %>%
slice(max(which(diff <= 0)):n())
# finds index of last element in "diff" which fullfills condition
#> # A tibble: 10 x 4
#> # Groups: group [3]
#> group date1 cut_off diff
#> <fct> <date> <date> <drtn>
#> 1 a 1970-01-05 1970-01-05 0 days
#> 2 a 1970-01-08 1970-01-05 3 days
#> 3 a 1970-01-13 1970-01-05 8 days
#> 4 a 1970-01-15 1970-01-05 10 days
#> 5 b 1970-01-07 1970-01-09 -2 days
#> 6 b 1970-01-11 1970-01-09 2 days
#> 7 b 1970-01-12 1970-01-09 3 days
#> 8 c 1970-01-10 1970-01-11 -1 days
#> 9 c 1970-01-14 1970-01-11 3 days
#> 10 c 1970-01-16 1970-01-11 5 days
由代表 package (v0.3.0) 於 2019 年 12 月 16 日創建
您可以檢測日期高於閾值的行,然后在它們上使用鉛以保持另一個值:
library(dplyr)
mydf %>%
arrange(group,date1) %>%
group_by(group) %>%
filter(lead(date1 > cut_off, default = TRUE)) %>%
ungroup()
#> # A tibble: 10 x 3
#> group date1 cut_off
#> <fct> <date> <date>
#> 1 a 1970-01-05 1970-01-05
#> 2 a 1970-01-08 1970-01-05
#> 3 a 1970-01-13 1970-01-05
#> 4 a 1970-01-15 1970-01-05
#> 5 b 1970-01-07 1970-01-09
#> 6 b 1970-01-11 1970-01-09
#> 7 b 1970-01-12 1970-01-09
#> 8 c 1970-01-10 1970-01-11
#> 9 c 1970-01-14 1970-01-11
#> 10 c 1970-01-16 1970-01-11
以下是dplyr
的幾種方法:
我們可以使用top_n
到 select 每個組的前 n 個日期,其中根據大於cut_off
的值的數量為每個組計算不同的n
。
library(dplyr)
mydf %>% group_by(group) %>% top_n(sum(date1 > cut_off) + 1, date1)
# group date1 cut_off
# <fct> <date> <date>
# 1 a 1970-01-05 1970-01-05
# 2 a 1970-01-08 1970-01-05
# 3 a 1970-01-13 1970-01-05
# 4 a 1970-01-15 1970-01-05
# 5 b 1970-01-11 1970-01-09
# 6 b 1970-01-12 1970-01-09
# 7 b 1970-01-07 1970-01-09
# 8 c 1970-01-14 1970-01-11
# 9 c 1970-01-16 1970-01-11
#10 c 1970-01-10 1970-01-11
盡管這會正確選擇行,但請注意top_n
不會對數據進行排序,因此您可能希望在鏈的末尾添加arrange(group, date1)
。
另一種方法類似於在 OP 中使用slice
發布的方法
mydf %>%
arrange(group, date1) %>%
group_by(group) %>%
slice((which.max(date1 > cut_off) - 1):n())
# group date1 cut_off
# <fct> <date> <date>
# 1 a 1970-01-05 1970-01-05
# 2 a 1970-01-08 1970-01-05
# 3 a 1970-01-13 1970-01-05
# 4 a 1970-01-15 1970-01-05
# 5 b 1970-01-07 1970-01-09
# 6 b 1970-01-11 1970-01-09
# 7 b 1970-01-12 1970-01-09
# 8 c 1970-01-10 1970-01-11
# 9 c 1970-01-14 1970-01-11
#10 c 1970-01-16 1970-01-11
我們也可以調整它以在filter
中使用。
mydf %>%
arrange(group, date1) %>%
group_by(group) %>%
filter(row_number() >= which.max(date1 > cut_off) - 1)
可以在基礎 R 中翻譯為:
new_df <- mydf[with(mydf, order(group, date1)), ]
subset(new_df, ave(date1 > cut_off, group, FUN = function(x)
seq_along(x) >= (which.max(x) - 1)))
我想按組刪除所有觀察到給定日期最近的觀察。 我不能簡單地使用 min(abs(x - date)) 計算最近的觀察值,因為在正面和負面中可能存在距離相等的觀察關系(例如,mydf 中的“b”組)。
你的標准是固定的,你需要有意識地選擇一種打破關系的方式——你可以選擇先出現的條目:(或最后一個,檢查?top_n)
mydf %>%
mutate(diff = abs(date1- cut_off)) %>%
arrange(group, diff) %>%
group_by(group) %>%
top_n(n = 1, wt = -diff )
# A tibble: 3 x 4
# Groups: group [3]
group date1 cut_off diff
<fct> <date> <date> <drtn>
1 a 1970-01-12 1970-01-11 1 days
2 b 1970-01-07 1970-01-02 5 days
3 c 1970-01-03 1970-01-04 1 days
*出於某種原因,即使在使用您的種子時,我也得到了不同的值 (8)
如果您只需要過濾 diff <= 0 的情況,只需將其添加到 pipe 鏈中。
排序和差異是明智之舉。 因此,對於最后一部分,由於您的日期已經排序,因此對於每個組,您使用 which.min 來調出最近的行,並保留 >= 此值的行:
mydf %>%
arrange(group, date1) %>%
group_by(group) %>%
mutate(delta = abs(date1- cut_off)) %>%
filter(1:n() >= max(which(delta == max(delta[delta<=0]))))
# A tibble: 10 x 4
# Groups: group [3]
group date1 cut_off delta
<fct> <date> <date> <drtn>
1 a 1970-01-05 1970-01-05 0 days
2 a 1970-01-08 1970-01-05 3 days
3 a 1970-01-13 1970-01-05 8 days
4 a 1970-01-15 1970-01-05 10 days
5 b 1970-01-07 1970-01-09 2 days
6 b 1970-01-11 1970-01-09 2 days
7 b 1970-01-12 1970-01-09 3 days
8 c 1970-01-10 1970-01-11 1 days
9 c 1970-01-14 1970-01-11 3 days
10 c 1970-01-16 1970-01-11 5 days
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.