Выберите значения из вектора, используя дату в качестве индекса

Предположим, у меня есть именованный вектор bar:

bar=c()
bar["1997-10-14"]=1
bar["2001-10-14"]=2
bar["2007-10-14"]=1

Как я могу выбрать из bar всех значений, для которых индекс находится в определенном диапазоне дат? Итак, если я ищу все значения между "1995-01-01" и "2000-06-01", я должен получить 1. И аналогично за период между "2001-09-01" и "2007-11-04" я должен получить 2 и 1.


r xts
person Pieter    schedule 29.04.2010    source источник
comment
К вашему сведению: вы создаете именованный числовой вектор, а не список.   -  person Shane    schedule 29.04.2010


Ответы (3)


Эта проблема была решена навсегда с помощью пакета xts, который расширяет функциональные возможности пакета zoo.

R> library(xts)
Loading required package: zoo
R> bar <- xts(1:3, order.by=as.Date("2001-01-01")+365*0:2)
R> bar
           [,1]
2001-01-01    1
2002-01-01    2
2003-01-01    3
R> bar["2002::"]        ## open range with a start year
           [,1]
2002-01-01    2
2003-01-01    3
R> bar["::2002"]        ## or end year
           [,1]
2001-01-01    1
2002-01-01    2
R> bar["2002-01-01"]    ## or hits a particular date
           [,1]
2002-01-01    2
R> 

Здесь есть намного больше, но основной момент заключается в том, чтобы не работать со строками, маскирующимися под даты.

Используйте тип Date или, что предпочтительнее, даже пакет расширения, созданный для эффективного индексирования миллионов дат.

person Dirk Eddelbuettel    schedule 29.04.2010

Вам нужно преобразовать даты из символов в тип Date с as.Date() (или тип POSIX, если у вас есть дополнительная информация, например время суток). Затем вы можете проводить сравнения со стандартными реляционными операторами, такими как ‹= и >=.

Для этого вам следует рассмотреть возможность использования пакета временных рядов, такого как zoo.

Изменить:

Просто чтобы ответить на ваш комментарий, вот пример использования дат с вашим существующим вектором:

> as.Date(names(bar)) < as.Date("2001-10-14")
[1]  TRUE FALSE FALSE
> bar[as.Date(names(bar)) < as.Date("2001-10-14")]
1997-10-14 
         1

Хотя вам действительно следует использовать пакет временных рядов. Вот как это можно сделать с помощью zoo (или xts, timeSeries, fts и т. д.):

library(zoo)
ts <- zoo(c(1, 2, 1), as.Date(c("1997-10-14", "2001-10-14", "2007-10-14")))
ts[index(ts) < as.Date("2001-10-14"),]

Поскольку индекс теперь имеет тип Date, вы можете делать столько сравнений, сколько хотите. Прочтите виньетку zoo для получения дополнительной информации.

person Shane    schedule 29.04.2010
comment
Хм, возможно, я делаю это неправильно, но если я сделаю что-то вроде bar[as.Date(2001-10-14)], я получу очень странные результаты, включающие множество NA. - person Pieter; 29.04.2010

Используя тот факт, что даты находятся в лексическом порядке:

bar[names(bar) > "1995-01-01" & names(bar) < "2000-06-01"]
# 1997-10-14 
#          1 

bar[names(bar) > "2001-09-01" & names(bar) < "2007-11-04"]
# 2001-10-14 2007-10-14 
#          2          1 

Результат называется вектором (поскольку вы исходный bar, это не список, а вектор).

Как утверждает Дирк в своем ответе, лучше использовать Date по соображениям эффективности. Без внешних пакетов вы можете переупорядочить данные и создать два вектора (или два столбца data.frame) один для дат, один для значений:

bar_dates <- as.Date(c("1997-10-14", "2001-10-14", "2007-10-14"))
bar_values <- c(1,2,1)

затем используйте простую индексацию:

bar_values[bar_dates > as.Date("1995-01-01") & bar_dates < as.Date("2000-06-01")]
# [1] 1

bar_values[bar_dates > as.Date("2001-09-01") & bar_dates < as.Date("2007-11-04")]
# [1] 2 1
person Marek    schedule 29.04.2010