2013-09-04 48 views
9

Tôi đã nhìn thấy nhiều câu hỏi (thường được liên kết với Order Bars in ggplot2 bar graph) về cách (lại) các loại đơn đặt hàng trong một âm mưu thanh.ô ggplot thanh với thứ tự phụ thuộc vào từng loại

Những gì tôi sau chỉ là một cảm ứng khác nhau, nhưng tôi không tìm được cách tốt để làm điều đó: Tôi có một âm mưu nhiều mặt, và tôi muốn đặt trục x cho từng khía cạnh một cách độc lập, theo đến một biến khác (trong trường hợp của tôi, biến đó chỉ là giá trị y, nghĩa là tôi chỉ muốn các thanh để tăng chiều dài trong mỗi khía cạnh).

Ví dụ đơn giản, sau ví dụ: Order Bars in ggplot2 bar graph:

df <- data.frame(name=c('foo','bar','foo','bar'),period=c('old','old','recent','recent'),val=c(1.23,2.17,4.15,3.65)) 
p = ggplot(data = df, aes(x = reorder(name, val), y = val)) 
p = p + geom_bar(stat='identity') 
p = p + facet_grid(~period) 
p 

Những gì chúng ta nhận được là như sau: enter image description here

Trong khi những gì tôi muốn là: enter image description here

+4

Ôi tốt lành! Bạn đang viết một followup để * Làm thế nào để Lie với Thống kê *? – John

+1

Cách duy nhất để làm điều này là tạo các ô riêng biệt và sử dụng 'grid.arrange' từ gói' gridExtra'. Nhưng tôi đồng ý rằng nó thường không dẫn đến một âm mưu rất hay. (Bạn sẽ thấy rằng rất nhiều trong ggplot, nếu một cái gì đó thực sự là khó để làm, nó có thể bởi vì nó đang cố gắng để giữ cho bạn khỏi làm một cái gì đó ngu ngốc.Không phải lúc nào, nhưng rất nhiều ...) – joran

+0

Vâng, cảm ơn, không phải siêu hữu ích, nhưng dù sao cũng được. Trong bối cảnh mà chúng ta đang sử dụng nó, nó là một cốt truyện quan trọng và thứ tự của các loại là rất thận trọng. Ở đây tôi đã đun nhỏ nó xuống một ví dụ tối thiểu, nhưng trong ứng dụng của chúng ta, chúng ta sắp xếp một tá tín hiệu trong chức năng của sự phụ thuộc đã nhận ra của chúng, và có các thanh đi khắp nơi trong một khía cạnh nào đó là không thể chấp nhận được. –

Trả lời

18

Ok, vì vậy tất cả triết lý sang một bên, và trong trường hợp có ai quan tâm, đây là một hack xấu xí để làm điều đó. Ý tưởng là sử dụng các nhãn khác nhau (suy nghĩ paste(period, name) ngoại trừ tôi thay thế khoảng thời gian thành 0 không gian, 1 dấu cách, v.v. để chúng không hiển thị). Tôi cần âm mưu này và tôi không muốn sắp xếp grobs và như thế, bởi vì tôi có thể muốn chia sẻ một huyền thoại phổ biến vv

Ví dụ nguyên tử cho trước đó trở thành:

df <- data.frame(name=c('foo','bar','foo','bar'), 
    period=c('old','old','recent','recent'), 
    val=c(1.23,2.17,4.15,3.65), 
    stringsAsFactors=F) 
df$n = as.numeric(factor(df$period)) 
df = ddply(df,.(period,name),transform, x=paste(c(rep(' ',n-1), name), collapse='')) 
df$x = factor(df$x, levels=df[order(df$val), 'x']) 
p = ggplot(data = df, aes(x = x, y = val)) 
p = p + geom_bar(stat='identity') 
p = p + facet_grid(~period, scale='free_x') 
p 

enter image description here Một Ví dụ, vẫn còn một chút ngớ ngẩn nhưng gần gũi hơn với trường hợp sử dụng thực tế của tôi, sẽ là:

df <- ddply(mpg, .(year, manufacturer), summarize, mixmpg = mean(cty+hwy)) 
df$manufacturer = as.character(df$manufacturer) 
df$n = as.numeric(factor(df$year)) 
df = ddply(df, .(year,manufacturer), transform, 
    x=paste(c(rep(' ',n-1), manufacturer), collapse='')) 
df$x = factor(df$x, levels=df[order(df$mixmpg), 'x']) 
p = ggplot(data = df, aes(x = x, y = mixmpg)) 
p = p + geom_bar(stat='identity') 
p = p + facet_grid(~year, scale='free_x') 
p = p + theme(axis.text.x=element_text(angle=90,hjust=1,vjust=.5,colour='gray50')) 
p 

enter image description here Nhắm mắt lại, suy nghĩ của Đế quốc, và cố gắng để thưởng thức.

+0

Tôi cộng oned câu trả lời bởi vì tôi nghĩ rằng nó mát mẻ mà nó có thể được thực hiện mà không có 'grid.arrange' nhưng một lần nữa tin rằng điều này có thể rất khó khăn trong đó kỳ vọng của chúng tôi về một đồ thị mặt là các loại sẽ được sắp xếp theo cùng một cách trên các khía cạnh. Đây có thể là một kỳ vọng bẩm sinh hoặc lịch sử, nhưng kỳ vọng là không có ít hơn và vi phạm nó có thể gây hiểu nhầm. –

+0

Tôi đồng ý với @TylerRinker về cả số lượng và đã bỏ phiếu cho phù hợp. Một tùy chọn khác (IMHO) có thể ít gây nhầm lẫn có thể là triệt tiêu nhãn trục hoàn toàn và chỉ sử dụng tính thẩm mỹ (nếu chỉ có một vài thanh) hoặc gắn nhãn chúng bên trong ô trên mỗi thanh. – joran

+0

Cảm ơn. Về cơ bản bạn đang đề xuất rằng x là thứ hạng (là một giá trị nhất quán, số) và vẽ văn bản của danh mục ở đâu đó bên trong mỗi thanh thay vì dưới dạng nhãn. Điều này có thể là vấn đề nếu một thanh nhỏ đối với một số danh mục, nhưng tôi luôn mở rộng cho sự đa dạng của các ý kiến. Có lẽ bạn có thể đưa ra một ví dụ, ví dụ: bằng cách sử dụng dữ liệu 'mpg', để chúng ta có thể thấy nó trông như thế nào. Là một tín đồ Tufte, sử dụng barplots sẽ không phải là lựa chọn đầu tiên của tôi, nhưng nó phù hợp với những gì Tyler gọi là "kỳ vọng lịch sử" (trong trường hợp này là của Công ty của tôi) ... –

1

Hãy thử điều này, nó thực sự đơn giản (Chỉ cần bỏ qua những lời cảnh báo)

df <-data.frame(name = c('foo', 'bar', 'foo', 'bar'), 
       period = c('old', 'old', 'recent', 'recent'), 
       val = c(1.23, 2.17, 4.15, 3.65)) 

d1 <- df[order(df$period, df$val), ] 
sn <- factor(x = 1:4, labels = d1$name) 
d1$sn <- sn 
p <- ggplot(data = d1, aes(x = sn, y = val)) 
p <- p + geom_bar(stat = 'identity') 
p <- p + facet_wrap(~ period, scale = 'free_x') 
p 
+0

Vì mục đích hoàn chỉnh: Các cảnh báo bị bỏ qua đã đọc: 'các mức độ trùng lặp trong các yếu tố không được chấp nhận'. – Uwe

4

Đây là một câu hỏi cũ nhưng nó được sử dụng như một mục tiêu dupe. Vì vậy, nó có thể là đáng giá để đề xuất một giải pháp sử dụng các cải tiến gần đây của gói ggplot2, cụ thể là thông số labels tới scale_x_discrete(). Điều này tránh được use duplicate levels không được dùng nữa hoặc đến manipulate factor labels by prepending a varying number of spaces.

Chuẩn bị dữ liệu

Ở đây, mpg bộ dữ liệu được sử dụng để có một so sánh để this answer. Đối với thao tác dữ liệu, gói data.table được sử dụng ở đây nhưng vui lòng sử dụng bất kỳ gói nào bạn thích cho mục đích này.

library(data.table) # version 1.10.4 
library(ggplot2)  # version 2.2.1 
# aggregate data 
df <- as.data.table(mpg)[, .(mixmpg = mean(cty + hwy)), by = .(year, manufacturer)] 
# create dummy var which reflects order when sorted alphabetically 
df[, ord := sprintf("%02i", frank(df, mixmpg, ties.method = "first"))] 

Tạo âm mưu

# `ord` is plotted on x-axis instead of `manufacturer` 
ggplot(df, aes(x = ord, y = mixmpg)) + 
    # geom_col() is replacement for geom_bar(stat = "identity") 
    geom_col() + 
    # independent x-axis scale in each facet, 
    # drop absent factor levels (actually not required here) 
    facet_wrap(~ year, scales = "free_x", drop = TRUE) + 
    # use named character vector to replace x-axis labels 
    scale_x_discrete(labels = df[, setNames(as.character(manufacturer), ord)]) + 
    # replace x-axis title 
    xlab(NULL) + 
    # rotate x-axis labels 
    theme(axis.text.x = element_text(angle = 90, hjust=1, vjust=.5)) 

enter image description here