Как построить 20 лет ежедневных данных во временных рядах

9

У меня есть следующий набор данных: https://dl.dropbox.com/u/22681355/ORACLE.csv и я хотел бы отобразить ежедневные изменения в «Open» по «Date», поэтому я сделал следующее:

oracle <- read.csv(file="http://dl.dropbox.com/u/22681355/ORACLE.csv", header=TRUE)
plot(oracle$Date, oracle$Open, type="l")

и я получаю следующее:

введите описание изображения здесь

Теперь это, очевидно, не самый хороший сюжет за всю историю, поэтому мне интересно, какой правильный метод использовать для построения таких подробных данных?

DBR
источник
1
Сюжет на самом деле не так уж и плох .... но как его улучшить, зависит от того, что вы хотите подчеркнуть. Вы хотите просто построить еженедельные данные? Хотите добавить плавную линию? Вы должны изменить метки оси X, конечно ....
Питер Флом
Да, я хотел бы иметь плавные линии, например, вот так: dl.dropbox.com/u/22681355/Untitled.tiff , все в порядке, если шкала указана в годах, но плавная линия будет существенной. Я пытался изменить тип на «l», но ничего не получалось.
DBR
В Rодин из способов добавить плавные линии является loess. Я уже ухожу, но попробуйте «loess in R» и, если у вас возникнут проблемы, отредактируйте свой пост, и кто-то наверняка сможет вам помочь. Есть и другие методы сглаживания, но я думаю, что loess - хороший вариант по умолчанию.
Питер Флом

Ответы:

8

Проблема с вашими данными не в том, что они очень подробные: у вас нет значений в выходные дни, поэтому они отображаются с пробелами. Есть два способа справиться с этим:

  1. Либо попробуйте угадать приблизительные значения в выходные дни с помощью некоторых методов сглаживания ( smooth.spline, loessи т. Д.). Код простой интерполяции приведен ниже. Но в этом случае вы привнесете в данные что-то «неестественное» и искусственное. Вот почему я предпочитаю второй вариант.
currentDate <- min(as.Date(oracle$Date))
dates <- c(currentDate)
openValues <- c(oracle$Open[5045])
i <- 5044
while (i > 0) {
  currentDate <- currentDate + 1;
  dates <- c(dates, currentDate)
  if (currentDate == as.Date(oracle$Date[i])) {
        # just copy value and move
        openValues <- c(openValues, oracle$Open[i])
        i <- i-1
      } else {
        # interpolate value
        openValues <- c(openValues, mean(oracle$Open[i:i-1]))
  }
}
plot(dates, openValues, type="l")
  1. Вы можете переходить от ежедневной к еженедельной основе, просто усредняя (например) пять последовательных точек, которые относятся к одной неделе (в этом случае вы «убиваете» некоторую информацию). Просто быстрый пример того, как это сделать
openValues = c(mean(oracle$Open[1:5]));
dates = c(as.Date(oracle$Date[1]));
for (i in seq(6,5045,5)) {
  openValues = c(openValues, mean(oracle$Open[i:i+5]));
      dates = c(dates, as.Date(oracle$Date[i]));
}
plot(dates, openValues, type="l")

Надеюсь, это поможет.

Дмитрий Лаптев
источник
1
спасибо, это действительно полезно проблема в том, что, поскольку это данные о запасах, переход от ежедневной к еженедельной основе может определенно «убить» некоторые важные данные. Есть ли способ иметь плавные линии для дней и пустые места для выходных?
DBR
Хорошо, если для вас важно не усреднять, я обновил ответ, предоставив пример кода для интерполяции выходных.
Дмитрий Лаптев
@dbr Кстати, если вы хотите полагаться на R в интерполяции, это было бы чрезвычайно просто:plot(as.Date(oracle$Date), oracle$Open, type='l')
Дмитрий Лаптев
1
И если вам просто нужны промежутки во время выходных, замените строку openValues <- c(openValues, mean(oracle$Open[i:i-1]))в первом методе наopenValues <- c(openValues, NA)
Дмитрий Лаптев
9

Поскольку эта проблема является общей для многих статистических программных сред, давайте обсудим ее здесь, посвященную перекрестной проверке, а не переносим ее на специализированный форум R (например, StackOverflow).

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

Сравнение участков

Чтобы составить правый график, Dateполе было преобразовано из фактора в фактическую дату, каждая неделя была идентифицирована с помощью простого вычисления (с разбивкой недель между субботой и воскресеньем), а линии были прерваны в выходные дни с циклическим изменением недель:

oracle$date <- as.Date(oracle$Date)
oracle$week.num <- (as.integer(oracle$date) + 3) %/% 7 
oracle$week <- as.Date(oracle$week.num * 7 - 3, as.Date("1970-01-01", "%Y-%m-%d"))

par(mfrow=c(1,2))
plot(as.factor(unclass(oracle$Date[1:120])), oracle$Open[1:120], type="l",
     main="Original Plot: Inset", xlab="Factor code")
plot(oracle$date[1:120], oracle$Open[1:120], type="n", ylab="Price", 
     main="Oracle Opening Prices")
tmp <- by(oracle[1:120,], oracle$week[1:120], function(x) lines(x$date, x$Open, lwd=2))

(Экран, эквивалентный каждой неделе, с указанием понедельника этой недели, также был сохранен в oracleкадре данных, поскольку он может быть полезен для построения еженедельных агрегированных данных.)

Исходное намерение может быть достигнуто простым эмуляцией последней строки для отображения всех данных. Чтобы добавить некоторую информацию о сезонном поведении, следующий график меняет цвет по неделям в течение каждого календарного года:

par(mfrow=c(1,1))
colors <- terrain.colors(52)
plot(oracle$date, oracle$Open, type="n", main="Oracle Opening Prices")
tmp <- by(oracle, oracle$week, 
          function(x) lines(x$date, x$Open, col=colors[x$week.num %% 52 + 1]))

Окончательный сюжет

Whuber
источник
Не финансист, но мне нравится сезонный тренд.
Джон Робертсон
@John Первоначально цвет был добавлен только, чтобы помочь глазу. Но, посмотрев на результат, я нахожу интересным, что за пять из шести лет, предшествовавших взрыву интернет-акций в 2000 году, оранжевые недели (примерно в конце лета) демонстрировали сильные тенденции к росту. Впоследствии эта тенденция, похоже, исчезла.
whuber
Я тоже это заметил и удивился, какими были отношения, если они вообще были.
Джон Робертсон
whuber и @John Robertson - Возможно, они не слишком тесно связаны, но в 1998 году Microsoft также перешла на свою современную кодовую базу с Sql Server 7.0 / Sql Server 2000, а к 2000 году они обеспечили более сильную конкуренцию Oracle: en.wikipedia.org/wiki/ Microsoft_SQL_Server # Genesis
Роб
1
@ Андре, я бы написал «Дата». Если это относительные даты, то, если позволяет пространство, я бы написал что-то вроде «Годы с 1 января 1990 года». В этом примере я надеюсь, что ясно, что подойдут только «годы» во множественном числе. Кстати, обычно я буду анализировать данные, связанные со временем, используя относительные даты (для числовой стабильности, удобства чтения статистических сводок и т. Д.), Но преобразую их обратно в фактические даты для графических дисплеев (потому что дисплеи должны использовать значимые, интерпретируемые единицы измерения) ,
whuber
1

Я не буду интерполировать на выходных. Очень немногие биржи торгуют в субботу, и ни одна, о которой я знаю в воскресенье. Вы вводите оценку для данных, которых никогда не было, так почему бы просто не удалить субботу и воскресенье из набора данных? Я хотел бы сделать что-то вроде ниже:

require(ggplot2)
require(scales)
require(gridExtra)
require(lubridate)
require(reshape)

set.seed(12345)

# Create data frame from random data
daysback <- 1000 # number of days, only a few for this example
startdate <- as.Date(format(now()), format = "%Y-%m-%d") - days(daysback)
mydf <- data.frame(mydate = seq(as.Date(startdate), by = "day", length.out = daysback),
                   open = runif(daysback, min = 600, max = 800))

# Now that we have a data frame, remove the weekend days
mydf <- mydf[!(weekdays(as.Date(mydf$mydate)) %in% c('Saturday','Sunday')),] # remove weekend days
    # Calculate change, except for the first date
    mydf$diff <- c(NA, diff(mydf$open))
    # Remove first row with no 'diff' value
    firstdate <- head(mydf$mydate, 1)
mydf <- mydf[mydf$mydate > firstdate, ]

p <- ggplot(mydf, aes(x = mydate, y = diff)) +
    geom_bar(data = mydf, stat = "identity", fill = "red")

print(p)
SlowLearner
источник
да, это то, что я хотел бы получить. но не проще ли просто оставить пустое пространство между строками, пропустив выходные?
DBR
Я думаю, что R предполагает, что если есть даты, их нужно использовать, поэтому вы должны удалить те, которые вам не нужны. В конце концов, это не сложно, приведенный выше код в основном излишний, важный бит - это удаление, для которого требуется только одна строка, т.е. mydf <- mydf [! (Weekdays (as.Date (mydf $ mydate)))% в% c («Суббота», «Воскресенье»),]
SlowLearner
но он уже удален в наборе данных, даты субботы и воскресенья не включены
dbr
Ах. Возможно, я совершенно неправильно понял ваш вопрос. Если вы просто хотите сгладить данные, то я согласен, что-то вроде лесс - это путь, но это изменит данные. Или вы можете создать очень, очень большое изображение графика, который показывает детали. 20000 пикселей в ширину или что-то, например.
SlowLearner
и как насчет использования решения Дмитрия, но вместо вменения среднего значения предыдущего и следующего значения, просто вменяя 0?
2012 года
0

Что касается внешнего вида вашего графика, я полагаю, что добавление нескольких меток под осью X визуально улучшит его. Внешний вид предлагаемого сюжета вы можете увидеть здесь http://imgur.com/ZTNPniA

Я не знаю, как сделать такой сюжет, это просто идея (которую я не видел реализованной в R)

Робин Гуд
источник