Cách vẽ 20 năm dữ liệu hàng ngày theo chuỗi thời gian


9

Tôi có bộ dữ liệu sau: https://dl.dropbox.com/u/22681355/ORACLE.csv và muốn vẽ các thay đổi hàng ngày trong 'Mở' trước 'Ngày', vì vậy tôi đã làm như sau:

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

và tôi nhận được như sau:

nhập mô tả hình ảnh ở đây

Bây giờ đây rõ ràng không phải là cốt truyện đẹp nhất từ ​​trước đến nay, vì vậy tôi tự hỏi đâu là phương pháp phù hợp để sử dụng khi vẽ dữ liệu chi tiết như vậy?


1
Cốt truyện thực sự không tệ lắm .... nhưng làm thế nào để cải thiện nó phụ thuộc vào những gì bạn muốn nhấn mạnh. Bạn có muốn chỉ vẽ dữ liệu hàng tuần? Bạn có muốn thêm một dòng mịn? Bạn nên thay đổi nhãn trục x, chắc chắn ....
Peter Flom

Có, tôi muốn có các đường trơn, ví dụ như thế này: dl.dropbox.com/u/22681355/Untitle.tiff , sẽ ổn nếu thang đo được tính bằng năm, nhưng đường trơn sẽ rất cần thiết. Tôi đã cố gắng thay đổi loại thành "l" nhưng nó không thực sự làm gì cả.
dbr

Trong Rmột cách để thêm các dòng mịn là loess. Tôi đang trên đường ra ngoài, nhưng hãy thử tham gia vào R và, nếu bạn gặp khó khăn, hãy chỉnh sửa bài đăng của bạn và ai đó chắc chắn sẽ có thể giúp bạn. Cũng có những phương pháp làm mịn khác, nhưng tôi nghĩ rằng hoàng thổ là một mặc định tốt.
Peter Flom

Câu trả lời:


8

Vấn đề với dữ liệu của bạn không phải là nó cực kỳ chi tiết: bạn không có giá trị vào cuối tuần, đó là lý do tại sao nó được vẽ với các khoảng trống. Có hai cách để đối phó với nó:

  1. Hoặc là cố gắng đoán giá trị gần đúng trong những ngày cuối tuần với một số phương pháp làm mịn ( smooth.spline, loess, vv). Mã nội suy đơn giản là dưới đây. Nhưng trong trường hợp này, bạn sẽ giới thiệu một cái gì đó "không tự nhiên" và nhân tạo cho dữ liệu. Đó là lý do tại sao tôi thích lựa chọn thứ hai.
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. Bạn có thể đi từ cơ sở hàng ngày đến cơ sở hàng tuần, chỉ cần tính trung bình (ví dụ) năm điểm liên tiếp xảy ra trong một tuần (trong trường hợp này bạn đang "giết" một số thông tin). Chỉ là một ví dụ nhanh về cách làm điều đó sẽ là
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")

Hy vọng nó sẽ giúp.


1
cảm ơn, điều này thực sự hữu ích vấn đề là vì đây là dữ liệu chứng khoán, việc chuyển từ cơ sở hàng ngày sang hàng tuần chắc chắn có thể 'giết' một số dữ liệu quan trọng. Có cách nào để có những đường trơn tru cho những ngày và không gian trống cho cuối tuần không?
dbr

Ok, nếu điều đó không quan trọng đối với bạn không trung bình, thì tôi đã cập nhật câu trả lời, cung cấp mã mẫu nội suy vào cuối tuần.
Dmitry Laptev

@dbr Nhân tiện, nếu bạn muốn dựa vào R trong phép nội suy, điều đó sẽ cực kỳ dễ dàng:plot(as.Date(oracle$Date), oracle$Open, type='l')
Dmitry Laptev

1
Và trong trường hợp bạn chỉ đơn giản muốn có những khoảng trống khi cuối tuần, hãy thay thế dòng openValues <- c(openValues, mean(oracle$Open[i:i-1]))trong phương pháp đầu tiên bằngopenValues <- c(openValues, NA)
Dmitry Laptev

9

Bởi vì vấn đề là phổ biến đối với nhiều môi trường phần mềm thống kê, chúng ta hãy thảo luận về vấn đề này ở đây trên Xác thực chéo thay vì di chuyển nó sang một diễn đàn dành riêng cho R (chẳng hạn như StackOverflow).

Các thực vấn đề là Dateđược coi là một yếu tố --một biến rời rạc - và do đó dòng không được kết nối đúng. (Cũng không phải là các điểm được vẽ hoàn toàn chính xác theo hướng ngang.)

Lô so sánh

Để thực hiện âm mưu bên phải, Datetrường được chuyển đổi từ một yếu tố thành một ngày thực tế, mỗi tuần được xác định bằng một phép tính đơn giản (phá vỡ các tuần giữa Thứ Bảy và Chủ Nhật) và các dòng bị gián đoạn trong những ngày cuối tuần bằng cách lặp qua các tuần:

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

(Một ngày tương đương với mỗi tuần, vào Thứ Hai của tuần đó, cũng được lưu trữ trong khung oracledữ liệu vì nó có thể hữu ích cho việc vẽ dữ liệu tổng hợp hàng tuần.)

Ý định ban đầu có thể đạt được chỉ bằng cách mô phỏng dòng cuối cùng để hiển thị tất cả dữ liệu. Để thêm một số thông tin về hành vi theo mùa, âm mưu sau thay đổi màu theo tuần trong mỗi năm dương lịch:

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

Cốt truyện cuối cùng


Không phải là một người tài chính, nhưng tôi thích thủ thuật xu hướng theo mùa.
John Robertson

@ John Ban đầu màu sắc được thêm vào chỉ để hỗ trợ mắt. Nhưng nhìn vào kết quả, tôi thấy thú vị rằng trong năm trong sáu năm trước khi xảy ra sự cố chứng khoán Internet vào năm 2000, các tuần màu cam (gần cuối mùa hè) đều thể hiện xu hướng tăng mạnh. Sau đó, xu hướng đó dường như đã biến mất.
whuber

Tôi cũng nhận thấy điều đó, và tự hỏi mối quan hệ, nếu có, là gì.
John Robertson

whuber và @John Robertson - Có thể không liên quan quá chặt chẽ nhưng năm 1998 cũng là khi Microsoft chuyển sang cơ sở mã hiện đại của họ với Sql Server 7.0 / Sql Server 2000 và đến năm 2000, họ đã cung cấp sự cạnh tranh mạnh mẽ hơn với Oracle: en.wikipedia.org/wiki/ Microsoft_Query_Server # Genesis
Cướp

1
@Andre tôi sẽ viết "Ngày". Nếu đó là ngày tương đối, thì - không gian cho phép - tôi sẽ viết một cái gì đó như "Năm kể từ ngày 1 tháng 1 năm 1990". Trong ví dụ đó, tôi hy vọng rằng chỉ có "năm" số nhiều sẽ làm. BTW, thông thường tôi sẽ phân tích dữ liệu liên quan đến thời gian bằng cách sử dụng ngày tương đối (để ổn định bằng số, dễ đọc tóm tắt thống kê, v.v.) nhưng sẽ chuyển đổi chúng thành ngày thực tế cho màn hình đồ họa (vì màn hình nên sử dụng các đơn vị đo lường có thể hiểu được) .
whuber

1

Tôi sẽ không nội suy vào cuối tuần. Rất ít giao dịch chứng khoán vào thứ bảy và không có gì tôi biết vào Chủ nhật. Bạn đang giới thiệu một ước tính cho dữ liệu chưa từng tồn tại, vậy tại sao không thay vào đó chỉ xóa thứ bảy và chủ nhật khỏi bộ dữ liệu? Tôi sẽ làm một cái gì đó như dưới đây:

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)

vâng, đây là những gì tôi muốn nhận được. nhưng không có cách nào dễ dàng hơn bằng cách chỉ để lại những khoảng trống giữa các dòng bằng cách "bỏ qua" những ngày cuối tuần?
dbr

Tôi nghĩ rằng R giả định rằng nếu có ngày, chúng sẽ được sử dụng, vì vậy bạn nên xóa những thứ bạn không muốn. Rốt cuộc, nó không khó, mã ở trên hầu hết là thừa, bit quan trọng là loại bỏ và chỉ yêu cầu một dòng, tức là mydf <- mydf [! (Các ngày trong tuần (as.Date (mydf $ mydate))% trong% c ('Thứ bảy', 'Chủ nhật')),]
SlowLearner

nhưng nó đã bị xóa trong bộ dữ liệu, không bao gồm ngày thứ bảy và chủ nhật
dbr

Ah. Tôi có thể đã hoàn toàn hiểu sai câu hỏi của bạn. Nếu bạn chỉ muốn làm mịn dữ liệu thì tôi đồng ý, một cái gì đó như hoàng thổ là cách để đi, nhưng điều đó sẽ thay đổi dữ liệu. Hoặc, bạn có thể tạo một hình ảnh rất, rất lớn của cốt truyện thể hiện chi tiết. 20.000 pixel hoặc một cái gì đó, ví dụ.
SlowLearner

và làm thế nào về việc sử dụng giải pháp của Dmitry nhưng thay vì sử dụng giá trị trung bình của giá trị trước đó và giá trị tiếp theo chỉ bằng 0?
dbr

0

Về giao diện của cốt truyện của bạn, tôi cho rằng việc thêm nhiều nhãn theo trục x sẽ cải thiện trực quan nó. Giao diện của đề xuất bạn có thể xem tại đây http://imgur.com/ZTNPniA

Tôi không biết làm thế nào để tạo ra cốt truyện như vậy, nó chỉ là một ý tưởng (mà tôi chưa thấy được thực hiện trong R)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.