Jak wykreślić 20 lat dziennych danych w szeregach czasowych

9

Mam następujący zestaw danych: https://dl.dropbox.com/u/22681355/ORACLE.csv i chciałbym zaplanować codzienne zmiany w „Otwarciu” według „Daty”, więc wykonałem następujące czynności:

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

i otrzymuję następujące:

wprowadź opis zdjęcia tutaj

Teraz nie jest to oczywiście najładniejszy wykres, więc zastanawiam się, jaka jest właściwa metoda, aby użyć takich szczegółowych danych?

dbr
źródło
1
Fabuła nie jest wcale taka zła .... ale jak ją poprawić, zależy od tego, co chcesz podkreślić. Czy chcesz po prostu wykreślić cotygodniowe dane? Czy chcesz dodać gładką linię? Z pewnością powinieneś zmienić etykiety osi x, na pewno ...
Peter Flom
Tak, chciałbym mieć gładkie linie, takie jak na przykład: dl.dropbox.com/u/22681355/Untitled.tiff , jest w porządku, jeśli skala jest w latach, ale gładka linia byłaby niezbędna. Próbowałem zmienić typ na „l”, ale tak naprawdę nic nie zrobiłem.
dbr
W Rjednym ze sposobów, aby dodać gładkie linie jest loess. Jestem w drodze do wyjścia, ale spróbuj? Less w R, a jeśli masz problemy, edytuj swój post, a ktoś na pewno będzie mógł ci pomóc. Istnieją również inne metody wygładzania, ale myślę, że less jest dobrym ustawieniem domyślnym.
Peter Flom

Odpowiedzi:

8

Problem z twoimi danymi nie polega na tym, że są one bardzo szczegółowe: w weekendy nie masz żadnych wartości, dlatego wykreślono je z przerwami. Istnieją dwa sposoby radzenia sobie z tym:

  1. Albo spróbuj odgadnąć wartości przybliżone w weekendy z niektórych metod wygładzających ( smooth.spline, loessetc.). Kod prostej interpolacji znajduje się poniżej. Ale w tym przypadku wprowadzisz do danych coś „nienaturalnego” i sztucznego. Dlatego wolę drugą opcję.
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. Możesz przejść od codziennej do tygodniowej, po prostu uśredniając (na przykład) pięć kolejnych punktów, które są podobne do jednego tygodnia (w tym przypadku „zabijasz” niektóre informacje). Byłby to tylko krótki przykład tego, jak to zrobić
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")

Mam nadzieję, że to pomoże.

Dmitrij Łaptiew
źródło
1
dzięki, to jest naprawdę pomocne. Problem polega na tym, że ponieważ są to dane giełdowe, przejście z codziennych na tygodniowe może zdecydowanie „zabić” niektóre kluczowe dane. Czy jest jakiś sposób na wygładzenie linii na dni i puste miejsca na weekendy?
dbr
Ok, jeśli ważne jest, abyś nie oceniał średnio, zaktualizowałem odpowiedź, podając przykładowy kod interpolacji weekendów.
Dmitry Laptev
@dbr Przy okazji, jeśli chcesz polegać na interpolacji R, byłoby to niezwykle łatwe:plot(as.Date(oracle$Date), oracle$Open, type='l')
Dmitrij Łaptiew
1
A jeśli po prostu chcesz zrobić przerwy w weekendy, zamień wiersz openValues <- c(openValues, mean(oracle$Open[i:i-1]))w pierwszej metodzie naopenValues <- c(openValues, NA)
Dmitrij Łaptiew
9

Ponieważ problem jest wspólny dla wielu środowisk oprogramowania statystycznego, omówmy go tutaj na Cross Validated, a nie migrujemy go na forum specyficzne dla języka R (takiego jak StackOverflow).

Prawdziwym problemem jest to, że Datejest traktowany jako czynnik -A zmiennej dyskretnej - i tak linie nie są prawidłowo podłączone. (Punkty nie są drukowane idealnie dokładnie w kierunku poziomym.)

Porównanie wykresów

Aby wykonać prawostronny wykres, Datepole zostało przekształcone ze współczynnika na rzeczywistą datę, każdy tydzień był identyfikowany za pomocą prostego obliczenia (przerywanie tygodni między sobotą a niedzielą), a linie były przerywane w weekendy przez zapętlanie w ciągu tygodni:

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))

(Odpowiednik daty każdego tygodnia, podając poniedziałek tego tygodnia, również został zapisany w oracleramce danych, ponieważ może być przydatny do kreślenia tygodniowych danych zagregowanych).

Pierwotny zamiar można osiągnąć po prostu przez emulację ostatniego wiersza w celu wyświetlenia wszystkich danych. Aby dodać informacje o sezonowym zachowaniu, poniższy wykres zmienia kolor w zależności od tygodnia w każdym roku kalendarzowym:

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]))

Ostateczna fabuła

Whuber
źródło
Nie jestem osobą finansową, ale podoba mi się sztuczka z trendami sezonowymi.
John Robertson,
@John Pierwotnie kolor został dodany tylko w celu ułatwienia oka. Ale patrząc na wynik, uważam za interesujące, że w ciągu pięciu z sześciu lat poprzedzających wybuch Internetu w 2000 r. Wszystkie pomarańczowe tygodnie (mniej więcej późne lato) wykazywały silne tendencje wzrostowe. Potem wydaje się, że ta tendencja zanikła.
whuber
Zauważyłem to i zastanawiałem się, jaki był związek.
John Robertson,
whuber i @John Robertson - Może nie być zbyt blisko spokrewniony, ale w 1998 r. Microsoft przeniósł się również do swojej nowoczesnej bazy kodów z Sql Server 7.0 / Sql Server 2000, a do 2000 r. zapewniał silniejszą konkurencję dla Oracle: en.wikipedia.org/wiki/ Microsoft_SQL_Server # Genesis
Rob
1
@ Andre napisałbym „Data”. Jeśli są to daty względne, to - jeśli pozwala na to miejsce - napisałbym coś w stylu „Lat od 1 stycznia 1990 roku”. W tym przykładzie mam nadzieję, że jasne będzie, że wystarczą tylko liczby mnogie. BTW, zwykle analizuję dane związane z czasem przy użyciu dat względnych (dla stabilności numerycznej, łatwości czytania podsumowań statystycznych itp.), Ale przekształcam je z powrotem w rzeczywiste daty dla wyświetlaczy graficznych (ponieważ wyświetlacze powinny używać znaczących, możliwych do interpretacji jednostek miar) .
whuber
1

Nie interpolowałbym w weekendy. Bardzo niewiele giełd papierów wartościowych handluje w sobotę, a żadnej nie znam w niedzielę. Wprowadzasz oszacowanie danych, które nigdy nie istniały, więc dlaczego zamiast tego po prostu usunąć sobotę i niedzielę ze zbioru danych? Zrobiłbym coś takiego:

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
źródło
tak, to chciałbym dostać. ale czy nie jest łatwiejszy sposób, pozostawiając puste przestrzenie między wierszami i „przeskakując” weekendy?
dbr
Myślę, że R zakłada, że ​​jeśli istnieją daty, są one do wykorzystania, więc powinieneś usunąć te, których nie chcesz. W końcu nie jest to trudne, powyższy kod jest w większości zbędny, ważnym bitem jest usunięcie i to wymaga tylko jednej linii, tj. Mydf <- mydf [! (Dni powszednie (as.Date (mydf $ mydate))% w% c („Sobota”, „Niedziela”)),]
SlowLearner
ale jest już usunięty z zestawu danych, daty soboty i niedzieli nie są uwzględnione
dbr
Ach Mogłem całkowicie nie zrozumieć twojego pytania. Jeśli chcesz tylko wygładzić dane, to zgadzam się, że coś w rodzaju „less” jest właściwą drogą, ale to zmieni dane. Lub możesz stworzyć bardzo, bardzo duży obraz fabuły, który pokazuje szczegóły. Na przykład szerokość 20 000 pikseli.
SlowLearner
a co powiesz na zastosowanie rozwiązania Dmitry'ego, ale zamiast przypisywać średnią z poprzedniej i następnej wartości tylko przypisując zero?
dbr
0

Jeśli chodzi o wygląd twojego wątku, przypuszczam, że dodanie wielu etykiet pod osią X poprawiłoby go wizualnie. Wygląd sugerowanej fabuły można zobaczyć tutaj http://imgur.com/ZTNPniA

Nie wiem, jak zrobić taką fabułę, to tylko pomysł (którego nie widziałem w R)

Robin Hood
źródło