2016-10-16 16 views
5

Tôi muốn tạo kiểu Geom mới: geom_ohlc(), cái gì đó giống như Biểu đồ Candlestick, để vẽ cổ phiếu mở cao-thấp- đóng dữ liệu.

Sau khi biết Hadley's article này: Tôi cố gắng này:

GeomOHLC <- ggproto(`_class` = "GeomOHLC", `_inherit` = Geom, 

       required_aes = c("x", "op", "hi", "lo", "cl"), 

       draw_panel = function(data, panel_scales, coord){ 

        coords <- coord$transform(data, panel_scales) 
        browser() # <<-- here is where I found the problem 
        grid::gList(
        grid::rectGrob(
         x = coords$x, 
         y = pmin(coords$op, coords$cl), 
         vjust = 0, 
         width = 0.01, 
         height = abs(coords$op - coords$cl), 
         gp = grid::gpar(col = coords$color, fill = "yellow") 
        ), 
        grid::segmentsGrob(
         x0 = coords$x, 
         y0 = coords$lo, 
         x1 = coords$x, 
         y1 = coords$hi 
         ) 
        ) 
       }) 
    geom_ohlc <- function(data = NULL, mapping = NULL, stat = "identity", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ...) 
    { 
     layer(
     geom = GeomOHLC, mapping = mapping, data = data, 
     stat = stat, position = position, show.legend = show.legend, 
     inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...) 
    ) 
    } 
    dt <- data.table(x = 1:10, open = 1:10, high = 3:12, low = 0:9, close = 2:11) 
    p <- ggplot(dt, aes(x = x, op = open, hi = high, lo = low, cl = close)) + 
     geom_ohlc() 
    p 

vì đơn giản, tôi chỉ cần không xem xét màu sắc của quán bar.

Cốt truyện kết quả là như thế này:

screenshot

tôi thêm một browser() bên trong ggproto chức năng, và tôi phát hiện ra rằng coord$transform không chuyển đổi op, hi, lo, cl thẩm mỹ vào interverl [ 0,1]. Cách khắc phục sự cố này?

Hơn nữa, có bất kỳ tài liệu nào khác về cách tạo kiểu Geom của riêng bạn ngoại trừ bài viết của Hadley không?

+0

Đổ lỗi có vẻ là 'transform_position()' được gọi bởi hàm trong 'coord $ transform'. Mã cho thấy rằng nó sẽ chỉ chuyển đổi các cột trong data.frame có tên là 'x' và' y'. Tôi không biết giải pháp cho vấn đề của bạn nhưng tôi sẽ cố gắng nghĩ xem liệu bạn có cần chúng * để được thay đổi kích thước (?). – ddiez

+0

Mặc dù trên suy nghĩ thứ hai cùng một mã cũng cho thấy khả năng của một số quy mô là "x" và/hoặc "y". Có lẽ có cái gì đó ở đó? – ddiez

+0

Ngoài ra, hàm 'ggplot2 ::: aes_to_scale' là hàm ánh xạ các tên' data.frame' cho dù chúng là thang đo 'x' hay' y'. Nhìn vào tài liệu bạn cần sử dụng '" x "," xmin "," xmax "," xend "," xintercept "' hoặc tính thẩm mỹ tương đương cho trục y. Nó cũng được đề cập trong '? Transform_position'. Tôi nghĩ rằng nếu bạn có thể tìm ra cách để ánh xạ các biến của bạn với những biến số bạn sẽ giải quyết được vấn đề của bạn. – ddiez

Trả lời

2

Như đã đề cập trong các nhận xét theo câu hỏi của OP, vấn đề là aes_to_scale() chức năng bên trong transform_position(), do đó được gọi là coord$transform. Biến đổi được giới hạn cho các biến có tên là x, xmin, xmax, xend, xintercept và các biến tương đương cho trục y. Điều này được đề cập trong trợ giúp cho transform_position:

Description

Convenience function to transform all position variables.

Usage

transform_position(df, trans_x = NULL, trans_y = NULL, ...) Arguments

trans_x, trans_y Transformation functions for x and y aesthetics. (will transform x, xmin, xmax, xend etc) ... Additional arguments passed to trans_x and trans_y.

Một cách giải quyết là sử dụng tên biến thay vì tên biến được OP sử dụng. Đoạn mã sau hoạt động trong việc chuyển đổi các biến nhưng nó không thành công ở một nơi khác (xem ở cuối). Tôi không biết chi tiết của âm mưu dự định, do đó, không cố gắng sửa lỗi này.

GeomOHLC <- ggproto(
    `_class` = "GeomOHLC", 
    `_inherit` = Geom, 

    required_aes = c("x", "yintercept", "ymin", "ymax", "yend"), 

    draw_panel = function(data, panel_scales, coord) { 
    coords <- coord$transform(data, panel_scales) 
    #browser() # <<-- here is where I found the problem 
    grid::gList(
     grid::rectGrob(
     x = coords$x, 
     y = pmin(coords$yintercept, coords$yend), 
     vjust = 0, 
     width = 0.01, 
     height = abs(coords$op - coords$cl), 
     gp = grid::gpar(col = coords$color, fill = "yellow") 
    ), 
     grid::segmentsGrob(
     x0 = coords$x, 
     y0 = coords$ymin, 
     x1 = coords$x, 
     y1 = coords$ymax 
    ) 
    ) 
    } 
) 
geom_ohlc <- 
    function(data = NULL, 
      mapping = NULL, 
      stat = "identity", 
      position = "identity", 
      na.rm = FALSE, 
      show.legend = NA, 
      inherit.aes = TRUE, 
      ...) 
    { 
    layer(
     geom = GeomOHLC, 
     mapping = mapping, 
     data = data, 
     stat = stat, 
     position = position, 
     show.legend = show.legend, 
     inherit.aes = inherit.aes, 
     params = list(na.rm = na.rm, ...) 
    ) 
    } 
dt <- 
    data.table(
    x = 1:10, 
    open = 1:10, 
    high = 3:12, 
    low = 0:9, 
    close = 2:11 
) 
p <- 
    ggplot(dt, aes(
    x = x, 
    yintercept = open, 
    ymin = high, 
    ymax = low, 
    yend = close 
)) + 
    geom_ohlc() 
p 

này biến đổi các biến nhưng tạo ra các lỗi sau:

Error in unit(height, default.units) : 
    'x' and 'units' must have length > 0 

Nhưng hy vọng từ đây nó có thể được thực hiện để làm việc.

LƯU Ý: Tôi đã chọn ánh xạ giữa các tên biến ban đầu (op, hi, lo, cl) thay vì tùy ý. Đặc biệt yintercept dường như không phù hợp. Có lẽ cần phải hỗ trợ các tên biến quy mô tùy ý trong ggplot2?

+0

Tôi nghĩ bạn có quan điểm. Tôi cố gắng thay đổi tên cột của 'dữ liệu' bên trong hàm' draw_panel', từ 'op, hi, lo, cl' thành' y, ymax, ymin, yend'. Sau đó, 'coords $ transfrom'" biết "để chuyển đổi các cột này thành [0, 1]. –

Các vấn đề liên quan