我有一个如下所示的数据库:
Year ID Date Occupy
2010 1 10 Yes
2010 2 11 No
2010 3 12 Yes
2010 4 9 No
2010 5 15 No
2011 7 7 Yes
2011 8 9 Yes
2011 9 10 Yes
2011 11 12 No
我正在尝试创建一个代码,首先检查每年哪些日期是第一个和最后一个被占用的日期(这里的日期是该月的日期)。在 2010 年,这些日期应该是 10 和 12,在 2011 年,这些日期应该是 7 和 10。然后代码应该过滤掉那些日期小于或大于这些第一个和最后一个占用日期的行。
结果应该是:
Year ID Date Occupy
2010 1 10 Yes
2010 2 11 No
2010 3 12 Yes
2011 7 7 Yes
2011 8 9 Yes
2011 9 10 Yes
我尝试使用以下方法在两个单独的部分中执行这两个步骤:
lapply(function(x) c(min(x), max(x)))
然后使用 lubridate 进行分组和过滤,但一切都会崩溃或不是我想要的。
单行
data.table
方法(可能不是最优雅的方法,但我最终想不出另一种方法;-))
library(data.table)
mydata <- fread(" Year ID Date Occupy
2010 1 10 Yes
2010 2 11 No
2010 3 12 Yes
2010 4 9 No
2010 5 15 No
2011 7 7 Yes
2011 8 9 Yes
2011 9 10 Yes
2011 11 12 No")
# or setDT(mydata)
mydata[mydata[Occupy == "Yes", .(min = min(Date), max = max(Date)), Year],
.(Year = x.Year, ID = x.ID, Date = x.Date, Occupy = x.Occupy),
on = .(Year, Date >= min, Date <= max)]
# Year ID Date Occupy
# 1: 2010 1 10 Yes
# 2: 2010 2 11 No
# 3: 2010 3 12 Yes
# 4: 2011 7 7 Yes
# 5: 2011 8 9 Yes
# 6: 2011 9 10 Yes
其他方法,相同的结果,更短的代码
mydata[ID %in% mydata[mydata[Occupy == "Yes", .(min = min(Date), max = max(Date)), Year],
ID, on = .(Year, Date >= min, Date <= max)], ]
如果您更喜欢
dplyr
语法:
library(dplyr)
df <- tribble(
~Year, ~ID, ~Date, ~Occupy,
2010, 1, 10, "Yes",
2010, 2, 11, "No",
2010, 3, 12, "Yes",
2010, 4, 9, "No",
2010, 5, 15, "No",
2011, 7, 7, "Yes",
2011, 8, 9, "Yes",
2011, 9, 10, "Yes",
2011, 11, 12, "No"
)
df |>
mutate(
min_occupied = min(Date[Occupy == "Yes"]),
max_occupied = max(Date[Occupy == "Yes"]),
.by = Year
) |>
filter(between(Date, min_occupied, max_occupied))
#> # A tibble: 6 × 6
#> Year ID Date Occupy min_occupied max_occupied
#> <dbl> <dbl> <dbl> <chr> <dbl> <dbl>
#> 1 2010 1 10 Yes 10 12
#> 2 2010 2 11 No 10 12
#> 3 2010 3 12 Yes 10 12
#> 4 2011 7 7 Yes 7 10
#> 5 2011 8 9 Yes 7 10
#> 6 2011 9 10 Yes 7 10
创建于 2023-11-08,使用 reprex v2.0.2