#r #date #dplyr
#r #Дата #dplyr
Вопрос:
У меня есть фрейм данных (df), подобный следующему:
derv market date
-10.7803563 Samp;P 500 Index 2008-01-02
-15.6922552 Samp;P 500 Index 2008-01-03
-15.7648483 Samp;P 500 Index 2008-01-04
-10.2294744 Samp;P 500 Index 2008-01-07
-0.5918593 Samp;P 500 Index 2008-01-08
8.1518987 Samp;P 500 Index 2008-01-09
.....
84.1518987 Samp;P 500 Index 2014-12-31
и я хочу найти 10 торговых дней в df до определенного дня. Например, 2008-01-12.
Я подумал об использовании dplyr следующим образом:
df %>% select(derv,Market,date) %>%
filter(date > 2008-01-12 - 10 amp; Date <2008-01-12)
но проблема, с которой я сталкиваюсь, заключается в том, как индексировать 10 торговых дней до определенного дня. Приведенный выше код не работает, и я не знаю, как с этим бороться в случае использования dplyr.
Другая проблема, связанная с проблемой, заключается в том, что конкретный день (например, 2008-01-12) может быть или не быть в df. Если конкретика находится в df, я думаю, мне нужно вернуться только на 9 дней назад для подсчета; но это не в df, мне нужно вернуться на 10 индексов. Я не уверен, прав ли я здесь или нет, но это та часть, которая меня смущает.
Был бы очень признателен за любую информацию.
Ответ №1:
Используя dplyr
и data.table::rleid()
Пример данных:
set.seed(123)
df=data.frame(derv=rnorm(18),Date=as.Date(c(1,2,3,4,6,7,9,11,12,13,14,15,18,19,20,21,23,24),origin="2008-01-01"))
Столбец с индексом создается для выбора не более чем за 10 дней до выбранной даты.
library(dplyr)
library(data.table)
df %>%
filter(Date < "2008-01-19") %>%
mutate(id = rleid(Date)) %>%
filter(id > (max(id)-10)) %>%
ungroup() %>%
select(derv,Date)
derv Date
1 -1.0678237 2008-01-04
2 -0.2179749 2008-01-05
3 -1.0260044 2008-01-07
4 -0.7288912 2008-01-08
5 -0.6250393 2008-01-10
6 -1.6866933 2008-01-12
7 0.8377870 2008-01-13
8 0.1533731 2008-01-14
9 -1.1381369 2008-01-15
10 1.2538149 2008-01-16
РЕДАКТИРОВАТЬ: решение Procrastinatus Maximus короче и требует только dplyr
df %>% filter(Date < "2008-01-19") %>% filter(row_number() > (max(row_number())-10))
Это дает тот же результат.
Комментарии:
1. Вы также можете использовать
id = row_number()
вместоrleid
😉2. Я думаю, достаточно всего двух вызовов
filter
:df %>% filter(Date < "2008-01-19") %>% filter(row_number() > (max(row_number())-10))
3. @ProcrastinatusMaximus: вы правы, я не подумал
row_number
, и это просто лучшее решение.
Ответ №2:
Итак, ответ на этот вопрос действительно зависит от того, как ваши даты хранятся в R. Но давайте предположим, что ISO 8601, как это выглядит на основе вашего кода.
Итак, сначала давайте создадим некоторые данные.
mydates <- as.Date("2007-06-22")
mydates<-c(mydates[1] 1:11, mydates[1] 14:19)
StockPrice<-c(1:17)
df<-data.frame(mydates,StockPrice)
Затем укажите интересующую дату, например @stats_guy
dateofinterest<-as.Date("2007-07-11")
Я бы сказал, используйте subset и просто вычтите 11 из вашей даты, поскольку она уже в этом формате.
foo<-subset(df, mydates<dateofinterest amp; mydates>(dateofinterest-11))
Тогда у вас будет хороший промежуток в 10 дней, но я не уверен, хотите ли вы 10 торговых дней? Или только 10 дней подряд, даже если это означает, что ваш список цен может быть меньше 10. Я намеренно создал свой набор данных с разрывами, подобными реальным рыночным данным, чтобы проиллюстрировать этот момент. Итак, я получил 8 значений за 10-дневный период вместо 10. Интересно услышать, что вы на самом деле ищете.
Допустим, вы действительно искали 10 торговых дней. Просто чтобы быть адвокатом дьявола здесь, вы могли бы предположить, что не будет более 10 десяти дней без торговли. Таким образом, мы возвращаемся на 20 дней назад до интересующей вас даты.
foo<-subset(df, mydates<dateofinterest amp; mydates>(dateofinterest-20))
Затем мы проверяем ваше подмножество данных, чтобы узнать, есть ли в нем более 10 торговых дней, используя if
инструкцию. Если строк более 10, то у вас слишком много дней. Мы просто обрезаем данные подмножества, foo
, до нужной длины, начиная с нижней части (последняя дата), а затем подсчитываем 9 записей оттуда. Теперь у вас есть десять торговых дней в хорошем аккуратном наборе данных.
if (nrow(foo)>10){
foo<-foo[(nrow(foo)-9):(nrow(foo)),]
}