Как создать дневной временной ряд, используя данные, которые не принимаются ежедневно - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть CSV-файл, который написан так:

Date        Data
1/5/1980    25
1/7/1980    30
2/13/1980   44
4/13/1980   50

Я бы хотел, чтобы R производил что-то вроде этого

Date        Date
1/1/1980    
1/2/1980
1/3/1980
1/4/1980
1/5/1980    25
1/6/1980 
1/7/1980    30

Тогда я бы хотел, чтобы R принес последниенаблюдение вперед, как это

Date        Date
1/1/1980    
1/2/1980
1/3/1980
1/4/1980
1/5/1980    25
1/6/1980    25
1/7/1980    30

Мне бы хотелось, чтобы две отдельные таблицы data.table создавали одну с фактическими данными, а другую с последним перенесенным последним наблюдением.

Спасибо за всю помощь!

Редактировать: мне также понадобятся любые NA, которые заполнены, чтобы изменить на 0

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Вы также можете использовать tidyverse:

library(tidyverse)

df %>%
  mutate(Date = as.Date(Date, "%m/%d/%Y")) %>%
  complete(Date = seq(as.Date(format(min(Date), "%Y-%m-01")), max(Date), by = "day")) %>%
  fill(Data) %>%
  replace(., is.na(.), 0)

Первые 10 строк:

# A tibble: 104 x 2
   Date        Data
   <date>     <dbl>
 1 1980-01-01     0
 2 1980-01-02     0
 3 1980-01-03     0
 4 1980-01-04     0
 5 1980-01-05    25
 6 1980-01-06    25
 7 1980-01-07    30
 8 1980-01-08    30
 9 1980-01-09    30
10 1980-01-10    30

Я использовал в качестве отправной точки 1-й день месяца и годаминимальная дата и максимальная максимальная дата;это, конечно, может быть откорректировано по мере необходимости.

РЕДАКТИРОВАТЬ: @Sotos предлагает еще лучшее предложение для более краткого подхода (с помощью лучшего использования аргумента format):

df %>%
  mutate(Date = as.Date(Date, "%m/%d/%Y")) %>%
  complete(Date = seq(as.Date(format(min(Date), "%Y-%m-01")), max(Date), by = "day")) %>%
  fill(Data)
0 голосов
/ 08 февраля 2019

Предполагая, что результат должен начинаться с первого числа месяца первой даты и заканчиваться последней датой, а фрейм входных данных DF, воспроизводимый в конце примечания, преобразуется DF вобъект зоопарка z, создайте сетку дат g, объедините их, чтобы получить объекты зоопарка z0 (с нулевым заполнением) и zz (с заполнением na.locf) и при желании преобразуйте обратно во фреймы данных или просто оставьтеэто как есть, поэтому вы можете использовать zoo для дальнейшей обработки.

library(zoo)

z <- read.zoo(DF, header = TRUE, format = "%m/%d/%Y")
g <- seq(as.Date(as.yearmon(start(z))), end(z), "day")

z0 <- merge(z, zoo(, g), fill = 0)  # zero filled
zz <- na.locf0(merge(z, zoo(, g)))  # na.locf filled

# optional
DF0 <- fortify.zoo(z0)  # zero filled
DF2 <- fortify.zoo(zz)  # na.locf filled

data.table

В вопросе упоминаются таблицы данных, и если это относится к пакету data.table, добавьте:

library(data.table)

DT0 <- data.table(DF0) # zero filled
DT2 <- data.table(DF2) # na.locf filled

Вариации

  1. Мне не было ясно, спрашивал ли вопрос о заполненном нулями ответе и na.locf заполненном ответе или просто na.locf заполненномответ, чьи оставшиеся значения NA заполнены 0, но принят первый случай.Если вы хотите заполнить НС, оставленные в na.locf заполненном ответе, добавьте:

    zz[is.na(zz)] <- 0
    
  2. Если вы хотите закончить в конце прошлого месяца, а не впоследнюю дату замените end(z) на as.Date(as.yearmon(end(z)), frac = 1).

  3. Если вы хотите начать с первого числа, а не с первого числа месяца первого числа, замените as.Date(as.yearmon(start(z))) на start(z).

  4. В качестве альтернативы (3), чтобы начать с первой даты и закончить с последней, мы могли бы просто преобразовать в ts и обратно.Обратите внимание, что нам нужно восстановить класс Date во второй строке ниже, поскольку класс ts не может напрямую обрабатывать класс Date.

    z2.na <- as.zoo(as.ts(z))
    time(z2.na) <- as.Date(time(z2.na))
    zz20 <- replace(z2.na, is.na(z2.na), 0)     # zero filled
    zz2 <- na.locf0(z2.na)                      # na.locf filled
    

Примечание

Lines <- "
Date        Data
1/5/1980    25
1/7/1980    30
2/13/1980   44
4/13/1980   50"
DF <- read.table(text = Lines, header = TRUE)
0 голосов
/ 08 февраля 2019

Решение:

  • создайте фрейм данных с последовательной датой
  • объедините его с вашими исходными данными. Фрейм
  • используйте na.locf функцию изzoo для переноса ваших данных

Вот код.Я использую lubridate для работы с датой.

library(lubridate)
df$Date <- mdy(df$Date)
successive <-data.frame(Date =  seq( as.Date(as.yearmon(df$Date[1])), df$Date[length(df$Date)], by="days"))

successive - вектор последовательных дат.Теперь слияние:

result <- merge(df,successive,all.y = T,on = "Date")

И прямое распространение:

library(zoo)
result$Data <- na.locf(result$Data,na.rm = F)


          Date Data
1   1980-01-05   25
2   1980-01-06   25
3   1980-01-07   30
4   1980-01-08   30
5   1980-01-09   30
6   1980-01-10   30
7   1980-01-11   30
8   1980-01-12   30
9   1980-01-13   30
10  1980-01-14   30
11  1980-01-15   30
12  1980-01-16   30
13  1980-01-17   30
14  1980-01-18   30
15  1980-01-19   30
16  1980-01-20   30
17  1980-01-21   30
18  1980-01-22   30
19  1980-01-23   30
20  1980-01-24   30
21  1980-01-25   30

Данные:

df <- read.table(text = "Date        Data
                 1/5/1980    25
                 1/7/1980    30
                 2/13/1980   44
                 4/13/1980   50", header = T)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...