2012-01-18 27 views
12

Tôi hy vọng tôi có thể kết hợp sức mạnh nhập khẩu và vẽ mạnh mẽ của grImport với sức mạnh đồ họa tuyệt vời của ggplot2, nhưng tôi đơn giản không hiểu hệ thống grid đủ tốt để tìm một cách thanh lịch để đạt được những gì tôi muốn. Điều tôi muốn là thay thế các nhãn dấu x trục trong biểu đồ ggplot2 bằng hình ảnh được nhập bằng cách sử dụng grImport.Làm cách nào tôi có thể sử dụng đồ họa được nhập bằng grImport làm nhãn đánh dấu trục trong ggplot2 (sử dụng chức năng lưới)?

Vì cả hai gói đều sử dụng các chức năng grid, tôi hy vọng có một cách để sử dụng grid.symbols() hoặc trong khuôn khổ ggplot2, điều này lý tưởng hoặc ít nhất trên một âm mưu hiện có trong thiết bị. Có ai có nhiều kiến ​​thức về những điều như vậy biết về một cách mạnh mẽ để làm điều này? Hoặc, bất cứ ai có thể chỉ cho tôi để biết thêm thông tin để giúp tôi tìm hiểu về grobs, viewports, vv? Tôi đã đọc qua free Chapter of Paul Murrel's R graphics book trên mô hình đồ họa lưới, nhưng tôi không đủ quen thuộc với các hoạt động bên trong của ggplot2 để tạo liên kết.

Câu hỏi của tôi rất giống với an existing question about using an image as a plot point, mặc dù tôi quan tâm nhiều hơn đến nhãn trục chứ không phải là điểm lô. Tuy nhiên, tôi sẽ tò mò về việc hai nhiệm vụ tương tự như thế nào, và nếu giải pháp đó có thể được điều chỉnh cho mục đích này. Tôi không thể tự mình tìm ra nó.

Đây là bài đăng đầu tiên của tôi, vì vậy tôi không được phép đăng hình ảnh, nhưng mã này đạt được điều gì đó gần với những gì tôi muốn. Lưu ý: cách tiếp cận này sử dụng một hack xấu xí, xấu xí không phải là di động và không đạt yêu cầu. Cốt truyện cuối cùng tôi muốn sản xuất sẽ có các khía cạnh (facet_grid) và trục x là một yếu tố với các hình ảnh khác nhau ở mỗi trục đánh dấu, không phải biến liên tục, đó là lý do tại sao tôi tìm kiếm tổng quát hơn/giải pháp mạnh mẽ không yêu cầu nhiều lỗi thử nghiệm &.

library(ggplot2) 
## library(grImport) # not needed for this example, but would be for grid.symbols() 

p <- ggplot(mtcars, aes(cyl, mpg)) + stat_summary(fun.data = "mean_cl_boot") 
print(p) 

## Replace (in this case, overlay) x-axis tick labels with a graphic/grob 
iconSize <- 0.05 
iconHt <- 0.2 
padding <- 0.09 # horizontal padding around axis: I found this by trial & error 
tickSp <- (1-padding)/(4*2) 
downViewport("axis_h-5-3") 
## I would use grid.symbols() with an imported Picture in place of grid.circle(), 
## but the idea is the same: draw a shape at the ticks along the axis. 
for (i in 0:(max(mtcars$cyl) - min(mtcars$cyl))) 
{ 
    grid.circle(x = (padding/2 + tickSp*(i*2)), y = iconHt, 
       r = iconSize*(min(mtcars$cyl)+i), gp = gpar(fill="black")) 
} 

upViewport() 
+0

một lựa chọn thay thế sẽ được sử dụng 'tikzDevice', và nhận được LaTeX tới [chèn đồ họa vector] (http://groups.google.com/group/ggplot2/browse_thread/thread/38f8695ad55cc2d6?pli=1) thay cho nhãn. – baptiste

+0

Cảm ơn tất cả các ví dụ hướng dẫn @baptiste!, Tôi mất một thời gian để xử lý tất cả, nhưng chúng rất hữu ích (xem bình luận bên dưới). Tôi sẽ giữ cho 'tikzDevice' trong tâm trí, mặc dù nó có vẻ như một chút quá mức cần thiết vào thời điểm này. Tôi đã thử ví dụ trong liên kết, nhưng không thành công với lỗi (LaTeX không thể hiểu được lệnh cho các hợp chất hóa học) và thực hiện một số thay đổi đối với phiên R của tôi mà tôi không thể tìm ra cách đảo ngược mà không bắt đầu lại R: ( –

+0

Vì vậy, gần gũi, nhưng tôi muốn có một hình ảnh khác nhau ở mỗi đánh dấu trục. Có thể bất kỳ giải pháp nào được điều chỉnh không?Ngoài ra, có cách nào để trích xuất các vị trí của các dấu x trục theo cách sao cho chúng có thể được sử dụng trong các cuộc gọi liên tiếp tới 'grid.symbols()' hoặc 'symbolsGrob()'? –

Trả lời

18

đây là một ví dụ:

# convert ps to RGML 
PostScriptTrace(file.path(system.file(package = "grImport"), "doc", "GNU.ps"), "GNU.xml") 
PostScriptTrace(file.path(system.file(package = "grImport"), "doc", "tiger.ps"), "tiger.xml") 
# read xml 
pics <- list(a = readPicture("GNU.xml"), b = readPicture("tiger.xml")) 

# custom function for x axis label. 
my_axis <- function() { 
    structure(
     function(label, x = 0.5, y = 0.5, ...) { 
     absoluteGrob(
      do.call("gList", mapply(symbolsGrob, pics[label], x, y, SIMPLIFY = FALSE)), 
      height = unit(1.5, "cm")) 
    } 
)} 

qplot(factor(c("a", "b")), 1:2) + opts(axis.text.x = my_axis()) 

enter image description here

+0

trong ggplot2 trong tương lai có thể có hệ thống trục như: '+ axis (x = axis_picture(), y = axis_text)', nhưng trong tương lai. – kohske

+0

ok, tôi lấy lại "xấu xí hack" của tôi được mô tả dưới đây;) này là khá gọn gàng tạo nên sự thiếu vectorisation của 'grid.symbols'. – baptiste

+0

Brilliant! Cảm ơn bạn và giữ cho công việc tuyệt vời. Thật tuyệt khi thấy các tính năng thú vị như thế này đang được lên kế hoạch cho ggplot2, nhưng nó vẫn ấn tượng rằng phần lớn nó có thể được thực hiện bằng đúng mã;) Tôi đã có thể thực hiện một số chỉnh sửa nhỏ để thực hiện chức năng tùy chỉnh chấp nhận danh sách hình ảnh như một đối số (tôi gọi là của tôi 'picture_axis()'), nhưng điều này là chính xác những gì tôi đã có tâm trí. Các bạn rock. –

6

Đối với một bảng duy nhất, nó khá thẳng về phía trước để trích xuất thông tin từ trục grob x và thay thế bằng thông tin của riêng bạn. Tôi không chắc chắn làm thế nào điều này có thể được mở rộng sạch sẽ để tự động, đa bảng điều khiển trục.

library(grid) 
library(ggplot2) 

p <- qplot(1:12, rnorm(12)) 
grid.newpage() 
g <- ggplotGrob(p) 
grid.draw(g) 
g0 <- getGrob(g, gPath("axis.text.x"), grep=TRUE) 
grid.set(gPath("axis.text.x"), 
     pointsGrob(x = g0$x, y=0*g0$x + unit(0.5,"npc"), 
        pch=19, gp=gpar(col=seq_along(g0$x)), 
        name = g0$name), grep = TRUE) 

screenshot

4

Dưới đây là một hack để sử dụng một grob tùy chỉnh cho nhãn trục.

library(grid) 
library(ggplot2) 

## convert the labels to some parameter to be used in the custom grob 
## here simply an index that will be interpreted as color 
mapping <- function(x, ...){ 
    seq_along(x) 
} 

library(grImport) 

hourglass <- new("Picture", 
paths= list(new("PictureFill", 
x=c(0, 1, 0, 1), 
y=c(0, 0, 1, 1))), 
summary= new("PictureSummary", 
numPaths=1, 
xscale=c(0, 1), 
yscale=c(0, 1))) 

## bare bones edit of theme_text() 
my_axis <- function() 
{ 
    structure(function(label, x = 0.5, y = 0.5, default.units = "npc", ...) { 
     cols <- mapping(label) 

     symbolsGrob(hourglass, x, 0*x + unit(0.5, "npc"), 
        use.gc=FALSE,size=unit(5,"mm"), gp=gpar(fill=cols)) 

    }, class = "theme", type = "custom", call = match.call()) 
} 

qplot(1:12, rnorm(12)) + 
    opts(axis.text.x = my_axis(), axis.ticks.margin = unit(0.5, "cm")) 

screenshot

+0

Tôi không chắc ai có thể (thanh lịch) sử dụng các hình dạng biểu tượng khác nhau tại mỗi địa điểm. – baptiste

+0

Tôi thực sự thích cách tiếp cận này, bởi vì nó giữ cốt truyện tương đối khép kín, và thậm chí nên làm việc với ggsave()! Tôi có thể xác nhận nó hoạt động với nhiều bảng điều khiển, NHƯNG ... Tôi thực sự cần phải có một hình ảnh khác nhau tại mỗi đánh dấu trục. Ý tưởng nào? –

+0

hỏi Paul Murrell? Tôi đã không nhìn thấy ví dụ về 'grid.symbols' với nhiều hình ảnh. Bạn có thể viết một hack xấu xí để "vectorize" 'grid.symbols' liên quan đến đối số hình ảnh bằng cách sử dụng một vòng lặp for (ví dụ, xem' drawDetails.pattern' trong gói 'gridExtra') – baptiste

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