[英]Creating a new date variable that is on the same day of the week, within the same month, and year as original date variable in r
我需要從日期變量“casedates”創建一個新變量“controldates”。 這個新變量將由與 casedate 在同一周的同一天,在與 case date 相同的月份和年份內的日期組成。 例如,如果我的案例日期是 7 月的第 3 個星期三,我的控制日將是 7 月的第一個星期三、7 月的第二個星期三和 7 月的第 4 個星期三。 此外,我想為創建的每組日期創建一個指標變量。 我想在 r 中使用 dplyr 來做到這一點。
起始數據:
Casedate
"01-03-2015"
"08-27-2017"
"10-23-2019"
這就是我想要的樣子
Casedate Controldate Index
"01-03-2015" "01-03-2015" 1
"01-03-2015" "01-10-2015" 1
"01-03-2015" "01-17-2015" 1
"01-03-2015" "01-24-2015" 1
"01-03-2015" "01-31-2015" 1
"08-12-2017" "08-05-2017" 2
"08-12-2017" "08-12-2017" 2
"08-12-2017" "08-19-2017" 2
"08-12-2017" "08-26-2017" 2
"10-23-2019" "10-02-2019" 3
"10-23-2019" "10-09-2019" 3
"10-23-2019" "10-16-2019" 3
"10-23-2019" "10-23-2019" 3
"10-23-2019" "10-30-2019" 3
這是tidyverse
一個選項。 轉換的“Casedate”到Date
類lubridate
,然后在與元素循環map
,創建一個seq
的日期uence list
, unnest
的list
列
library(dplyr)
library(purrr)
library(lubridate)
df1 %>%
mutate(Index = row_number(),
Casedate = mdy(Casedate),
wd = wday(Casedate, label = TRUE),
Controldate = map2(floor_date(Casedate, 'month'), wd, ~ {
x1 <- seq(.x, length.out = 7, by = '1 day')
seq(x1[wday(x1, label = TRUE) == .y],
ceiling_date(.x, 'month'), by = '7 day')})) %>%
unnest(c(Controldate)) %>%
select(Casedate, Controldate, Index)
-輸出
# A tibble: 14 x 3
# Casedate Controldate Index
# <date> <date> <int>
# 1 2015-01-03 2015-01-03 1
# 2 2015-01-03 2015-01-10 1
# 3 2015-01-03 2015-01-17 1
# 4 2015-01-03 2015-01-24 1
# 5 2015-01-03 2015-01-31 1
# 6 2017-08-27 2017-08-06 2
# 7 2017-08-27 2017-08-13 2
# 8 2017-08-27 2017-08-20 2
# 9 2017-08-27 2017-08-27 2
#10 2019-10-23 2019-10-02 3
#11 2019-10-23 2019-10-09 3
#12 2019-10-23 2019-10-16 3
#13 2019-10-23 2019-10-23 3
#14 2019-10-23 2019-10-30 3
df1 <- structure(list(Casedate = c("01-03-2015", "08-27-2017", "10-23-2019"
)), class = "data.frame", row.names = c(NA, -3L))
由於一個月內最多只能有 4 周或 4 周后的日期(總共 9 個值),因此您可以通過一些序列一次性計算該范圍。 這應該避免需要顯式循環每個值。
計算完這些值后,然后在一次掃描中將其子集到與原始值相同的月份。 使用@akrun 的df1
示例數據來自下面:
d <- as.Date(df1$Casedate, format="%m-%d-%Y")
r <- rep(d, each=9)
o <- r + (7 * -4:4)
i <- rep(seq_along(d), each=9)
s <- format(o, "%m") == format(r, "%m")
data.frame(
Casedate = r,
Controldate = o,
Index = i
)[s,]
# Casedate Controldate Index
#5 2015-01-03 2015-01-03 1
#6 2015-01-03 2015-01-10 1
#7 2015-01-03 2015-01-17 1
#8 2015-01-03 2015-01-24 1
#9 2015-01-03 2015-01-31 1
#11 2017-08-27 2017-08-06 2
#12 2017-08-27 2017-08-13 2
#13 2017-08-27 2017-08-20 2
#14 2017-08-27 2017-08-27 2
#20 2019-10-23 2019-10-02 3
#21 2019-10-23 2019-10-09 3
#22 2019-10-23 2019-10-16 3
#23 2019-10-23 2019-10-23 3
#24 2019-10-23 2019-10-30 3
如果你想保留數據集中的所有原始變量,這是一個簡單的修復:
cbind(
df1[i,],
data.frame(Controldate = o, Index = i)
)[s,]
例如:
# Casedate othvar1 othvar2 Controldate Index
#1.4 01-03-2015 a B 2015-01-03 1
#1.5 01-03-2015 a B 2015-01-10 1
#1.6 01-03-2015 a B 2015-01-17 1
#1.7 01-03-2015 a B 2015-01-24 1
#...
即使在中等大的數據集(300K 行)上,生成序列運行(2 秒)和循環每個值(2 分鍾)之間的時間也存在有意義的差異:
序列:
df1 <- df1[rep(1:3,each=1e5),,drop=FALSE]
system.time({
d <- as.Date(df1$Casedate, format="%m-%d-%Y")
r <- rep(d, each=9)
o <- r + (7 * -4:4)
i <- rep(seq_along(d), each=9)
s <- format(o, "%m") == format(r, "%m")
data.frame(
Casedate = r,
Controldate = o,
Index = i
)[s,]
})
# user system elapsed
# 1.909 0.128 2.038
循環:
library(dplyr)
library(purrr)
library(lubridate)
system.time({
df1 %>%
mutate(Index = row_number(),
Casedate = mdy(Casedate),
wd = wday(Casedate, label = TRUE),
Controldate = map2(floor_date(Casedate, 'month'), wd, ~ {
x1 <- seq(.x, length.out = 7, by = '1 day')
seq(x1[wday(x1, label = TRUE) == .y],
ceiling_date(.x, 'month'), by = '7 day')})) %>%
unnest(Controldate) %>%
select(Casedate, Controldate, Index)
})
# user system elapsed
# 131.466 1.143 132.623
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.