Это можно сделать в одной строке без пакетов или ifelse
, если мы используем именованный вектор
df$Date <- with(df, Date - setNames(rep(0:2, c(5, 1, 1)), 1:7)[format(Date, "%u")])
df
# Ticker Date mean_PX_ASK mean_PX_BID Agency
#1 ABNANV 2007-03-02 102.0 102.0 Moody's
#2 ABNANV 2007-03-02 102.0 102.0 Moody's
#3 ABNANV 2007-03-12 102.0 102.0 Moody's
#4 ABNANV 2007-03-12 102.0 102.0 Moody's
#5 ABNANV 2008-09-17 88.9 88.4 Fitch
#6 ABNANV 2008-09-17 88.9 88.4 Fitch
Тесты
Использование большего набора данных
df1 <- df[rep(seq_len(nrow(df)), 1e7), ]
system.time({
df1 %>%
mutate(Day = weekdays(Date),
Date = case_when(Day == "Saturday" ~ Date - 1,
Day == "Sunday" ~ Date - 2,
TRUE ~ Date)) %>%
select(-Day)
})
# user system elapsed
# 41.468 6.881 49.588
system.time({
with(df1, Date - setNames(rep(0:2, c(5, 1, 1)), 1:7)[format(Date, "%u")])
})
# user system elapsed
# 27.456 2.785 30.490
с microbenchmark
,
library(microbenchmark)
microbenchmark(
rs = df1 %>%
mutate(Day = weekdays(Date),
Date = case_when(Day == "Saturday" ~ Date - 1,
Day == "Sunday" ~ Date - 2,
TRUE ~ Date)) %>%
select(-Day),
ak = with(df1, Date - setNames(rep(0:2, c(5, 1, 1)), 1:7)[format(Date, "%u")]),
times = 10L, unit = "relative")
#Unit: relative
# expr min lq mean median uq max neval cld
# rs 1.401658 1.437164 1.446403 1.421731 1.512451 1.467511 10 b
# ak 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 10 a
Данные
df <- structure(list(Ticker = c("ABNANV", "ABNANV", "ABNANV", "ABNANV",
"ABNANV", "ABNANV"), Date = structure(c(13575, 13576, 13584,
13584, 14139, 14139), class = "Date"), mean_PX_ASK = c(102, 102,
102, 102, 88.9, 88.9), mean_PX_BID = c(102, 102, 102, 102, 88.4,
88.4), Agency = c("Moody's", "Moody's", "Moody's", "Moody's",
"Fitch", "Fitch")), row.names = c("1", "2", "3", "4", "5", "6"
), class = "data.frame")