2014-10-22 32 views
41

Tôi có một chức năng điều khiển đối tượng ggplot, bằng cách chuyển đổi nó thành grob và sau đó sửa đổi các lớp. Tôi muốn hàm trả về một đối tượng ggplot không phải là một grob. Có một cách đơn giản để chuyển đổi một grob trở lại gg?Đảo ngược của ggplotGrob?

The documentation trên ggplotGrob hết sức thưa thớt.
đơn giản ví dụ:

P <- ggplot(iris) + geom_bar(aes(x=Species, y=Petal.Width), stat="identity") 

G <- ggplotGrob(P) 
... some manipulation to G ... 

## DESIRED: 
P2 <- inverse_of_ggplotGrob(G) 

such that, we can continue to use basic ggplot syntax, ie 
`P2 + ylab ("The Width of the Petal")` 

UPDATE:

Để trả lời các câu hỏi trong các bình luận, động lực ở đây là để thay đổi màu sắc của nhãn khía cạnh lập trình, dựa trên giá trị của tên nhãn trong mỗi khía cạnh. Các chức năng dưới đây hoạt động tốt (dựa trên đầu vào từ báp-têm trong câu hỏi trước).

Tôi muốn giá trị trả lại từ colorByGroup trở thành đối tượng ggplot, không chỉ đơn giản là một grob.

Đây là mã, cho những người quan tâm

get_grob_strips <- function(G, strips=grep(pattern="strip.*", G$layout$name)) { 

    if (inherits(G, "gg")) 
    G <- ggplotGrob(G) 
    if (!inherits(G, "gtable")) 
    stop ("G must be a gtable object or a gg object") 

    strip.type <- G$layout[strips, "name"] 
    ## I know this works for a simple 
    strip.nms <- sapply(strips, function(i) { 
    attributes(G$grobs[[i]]$width$arg1)$data[[1]][["label"]] 
    }) 

    data.table(grob_index=strips, type=strip.type, group=strip.nms) 
} 


refill <- function(strip, colour){ 
    strip[["children"]][[1]][["gp"]][["fill"]] <- colour 
    return(strip) 
} 

colorByGroup <- function(P, colors, showWarnings=TRUE) { 
## The names of colors should match to the groups in facet 
    G <- ggplotGrob(P) 
    DT.strips <- get_grob_strips(G) 

    groups <- names(colors) 
    if (is.null(groups) || !is.character(groups)) { 
    groups <- unique(DT.strips$group) 
    if (length(colors) < length(groups)) 
     stop ("not enough colors specified") 
    colors <- colors[seq(groups)] 
    names(colors) <- groups 
    } 


    ## 'groups' should match the 'group' in DT.strips, which came from the facet_name 
    matched_groups <- intersect(groups, DT.strips$group) 
    if (!length(matched_groups)) 
    stop ("no groups match") 
    if (showWarnings) { 
     if (length(wh <- setdiff(groups, DT.strips$group))) 
     warning ("values in 'groups' but not a facet label: \n", paste(wh, colapse=", ")) 
     if (length(wh <- setdiff(DT.strips$group, groups))) 
     warning ("values in facet label but not in 'groups': \n", paste(wh, colapse=", ")) 
    } 

    ## identify the indecies to the grob and the appropriate color 
    DT.strips[, color := colors[group]] 
    inds <- DT.strips[!is.na(color), grob_index] 
    cols <- DT.strips[!is.na(color), color] 

    ## Fill in the appropriate colors, using refill() 
    G$grobs[inds] <- mapply(refill, strip = G$grobs[inds], colour = cols, SIMPLIFY = FALSE) 

    G 
} 

Trả lời

8

tôi sẽ nói không. ggplotGrob là đường một chiều. đối tượng grob đang vẽ nguyên thủy được xác định bởi lưới. Bạn có thể tạo các rãnh tùy ý từ đầu. Không có cách nào chung để biến một bộ sưu tập ngẫu nhiên các grobs trở lại thành một hàm sẽ tạo ra chúng (nó không thể đảo ngược vì nó không phải là 1: 1). Một khi bạn đi grob, bạn không bao giờ quay trở lại.

Bạn có thể bọc một đối tượng ggplot trong một lớp tùy chỉnh và quá tải các lệnh in/lệnh để thực hiện một số thao tác grob tùy chỉnh, nhưng đó có thể là hack-ish hơn.