Як побудувати графік 20 років щоденних даних у часових рядах


9

У мене є такий набір даних: https://dl.dropbox.com/u/22681355/ORACLE.csv, і я хотів би побудувати щоденні зміни у "Відкрити" на "Дата", тому я зробив наступне:

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

і я отримую наступне:

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

Зараз це, очевидно, не найприємніший сюжет коли-небудь, тому мені цікаво, який правильний метод використовувати при побудові таких детальних даних?


1
Сюжет насправді не такий вже й поганий .... але як його покращити залежить від того, що ви хочете підкреслити. Ви хочете просто скласти щотижневі дані? Ви хочете додати плавну лінію? Вам, звичайно, слід змінити мітки осі x ....
Пітер Флом

Так, я хотів би мати гладкі лінії, як, наприклад, така: dl.dropbox.com/u/22681355/Untitled.tiff , це нормально, якщо шкала знаходиться в роках, але гладка лінія буде суттєвою. Я намагався змінити тип на "l", але це насправді нічого не робило.
грудня

В Rодин з способів додати плавні лінії є loess. Я виходжу, але спробуйте? Loess у R, і якщо у вас виникли проблеми, відредагуйте свою посаду, і хтось, безумовно, зможе вам допомогти. Є й інші методи згладжування, але я вважаю, що льос - це хороший дефолт.
Пітер Флом

Відповіді:


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 До речі, якщо ви хочете покластися на 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]))

Заключний сюжет


Не людина, яка займається фінансами, але мені подобається трюковий сезонний трюк.
Джон Робертсон

@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
@Andre я написав би "Дата". Якщо це відносні дати, то, якщо це дозволить, - я б написав щось на кшталт "Роки з 1 січня 1990 року". У цьому прикладі я сподіваюся, що зрозуміло, що тільки множина "років" виконає. BTW, як правило, я буду аналізувати дані, пов'язані з часом, використовуючи відносні дати (для чисельної стійкості, зручності читання статистичних зведень тощо), але перетворять їх у фактичні дати для графічних дисплеїв (оскільки на дисплеях повинні використовуватися значущі, інтерпретовані одиниці вимірювання) .
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)

так, саме це я хотів би отримати. але чи не існує простішого способу, просто залишивши порожні проміжки між рядками, провівши "пропустити" вихідні?
грудня

Я думаю, що R передбачає, що якщо є дати, вони є там, щоб їх використовувати, тому ви повинні видалити ті, які не хочете. Зрештою, це не важко, наведений вище код здебільшого зайвий, важливим бітом є видалення і вимагає лише одного рядка, тобто mydf <- mydf [! (Будні (as.Date (mydf $ mydate))% у% c ('Субота', 'Неділя')),]
SlowLearner

але його вже видалено в набір даних, дати субота та неділя не включаються
1212

Ага. Можливо, я повністю зрозумів ваше запитання. Якщо ви просто хочете згладити дані, то я погоджуюся, щось на зразок лес - це шлях, але це змінить дані. Або ви можете створити дуже-дуже великий образ сюжету, який показує деталь. Наприклад, 20000 пікселів або щось подібне.
SlowLearner

а як щодо використання рішення Дмитра, але замість того, щоб вводити середнє значення попереднього та наступного значення, просто вводячи 0?
грудня

0

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.