Sắp xếp tỷ lệ x rời rạc theo tần số / giá trị


137

Tôi đang tạo một biểu đồ thanh tránh được bằng ggplot với tỷ lệ x rời rạc, trục x hiện được sắp xếp theo thứ tự bảng chữ cái, nhưng tôi cần sắp xếp lại để nó được sắp xếp theo giá trị của trục y (nghĩa là thanh cao nhất sẽ được đặt ở bên trái).

Tôi đã thử đặt hàng hoặc sắp xếp, nhưng kết quả là sắp xếp trục x, nhưng không tương ứng với các thanh.

Tôi đã làm gì sai?

Câu trả lời:


105

Thử đặt thủ công các mức của yếu tố trên trục x. Ví dụ:

library(ggplot2)
# Automatic levels
ggplot(mtcars, aes(factor(cyl))) + geom_bar()    

ggplot của bộ dữ liệu xe hơi với các mức yếu tố tự động được xác định

# Manual levels
cyl_table <- table(mtcars$cyl)
cyl_levels <- names(cyl_table)[order(cyl_table)]
mtcars$cyl2 <- factor(mtcars$cyl, levels = cyl_levels)
# Just to be clear, the above line is no different than:
# mtcars$cyl2 <- factor(mtcars$cyl, levels = c("6","4","8"))
# You can manually set the levels in whatever order you please. 
ggplot(mtcars, aes(cyl2)) + geom_bar()

ggplot của bộ dữ liệu xe hơi với các cấp độ yếu tố được sắp xếp lại theo cách thủ công

Như James đã chỉ ra trong câu trả lời của mình, reorderlà cách thành ngữ để sắp xếp lại các cấp độ yếu tố.

mtcars$cyl3 <- with(mtcars, reorder(cyl, cyl, function(x) -length(x)))
ggplot(mtcars, aes(cyl3)) + geom_bar()

ggplot của bộ dữ liệu ô tô với các mức yếu tố được sắp xếp lại bằng cách sử dụng chức năng sắp xếp lại


197

Cách tốt nhất đối với tôi là sử dụng vector với các danh mục để tôi cần làm limitstham số scale_x_discrete. Tôi nghĩ rằng nó là giải pháp khá đơn giản và đơn giản.

ggplot(mtcars, aes(factor(cyl))) + 
  geom_bar() + 
  scale_x_discrete(limits=c(8,4,6))

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


1
@HendyI Girls không có chú thích trừ khi bạn có các kích thước khác (màu sắc, màu tô) cũng được ánh xạ tới cùng một biến.
Gregor Thomas

5
Tôi nghĩ rằng đây là câu trả lời tốt nhất. Nó kiểm soát thứ tự của các giá trị trục x và không biến đổi hoặc ảnh hưởng đến khung dữ liệu. Việc sử dụng factorreorderthay đổi các đặc điểm của dữ liệu, mặc dù trong ggplot()cuộc gọi, và nhiều hơn những gì nó cần làm cho vấn đề hiện tại.
mjandrews

2
Đây phải là câu trả lời được chấp nhận !! Tại sao làm phức tạp mọi thứ bằng cách viết 2 đến 3 dòng mã cho một thứ bạn có thể làm trong một dòng mã thanh lịch (được xác định trước)?
SilSur

1
Điều này cũng giúp tôi đặt hàng x theo giá trị của y: scale_x_discrete(limits = DT$x[order(-DT$y)])+
armipunk

38

Bạn có thể sử dụng reorder:

qplot(reorder(factor(cyl),factor(cyl),length),data=mtcars,geom="bar")

Biên tập:

Để có thanh cao nhất ở bên trái, bạn phải sử dụng một chút bùn:

qplot(reorder(factor(cyl),factor(cyl),function(x) length(x)*-1),
   data=mtcars,geom="bar")

Tôi hy vọng điều này cũng có chiều cao tiêu cực, nhưng nó không, vì vậy nó hoạt động!


5
Tôi bị sốc vì câu trả lời này không có nhiều sự ủng hộ hơn, 90% thời gian đây là cách thích hợp để làm điều đó.
Gregor Thomas

1
Tôi nghĩ rằng cả hai yếu tố cuộc gọi là thừa. Có một lệnh gọi ngầm định cho hệ số cho đối số thứ nhất và đối số thứ hai hte được coi là số.
IRTFM

Một lời giải thích giúp tôi tìm ra những gì các giải pháp này đang thực hiện trong chương trình: rstudio-pub-static.s3.amazonaws.com/ tựa
keithpjcar

30

Hadley đã được phát triển một gói gọi là forcats. Gói này làm cho nhiệm vụ dễ dàng hơn nhiều. Bạn có thể khai thác fct_infreq()khi bạn muốn thay đổi thứ tự trục x theo tần số của một yếu tố. Trong trường hợp mtcarsví dụ trong bài đăng này, bạn muốn sắp xếp lại các cấp cyltheo tần suất của từng cấp. Mức độ xuất hiện thường xuyên nhất ở phía bên trái. Tất cả bạn cần là fct_infreq().

library(ggplot2)
library(forcats)

ggplot(mtcars, aes(fct_infreq(factor(cyl)))) +
geom_bar() +
labs(x = "cyl")

Nếu bạn muốn đi theo con đường khác, bạn có thể sử dụng fct_rev()cùng với fct_infreq().

ggplot(mtcars, aes(fct_rev(fct_infreq(factor(cyl))))) +
geom_bar() +
labs(x = "cyl") 

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


2

Tôi nhận ra điều này đã cũ, nhưng có lẽ chức năng này tôi tạo ra rất hữu ích cho ai đó ngoài kia:

order_axis<-function(data, axis, column)
{
  # for interactivity with ggplot2
  arguments <- as.list(match.call())
  col <- eval(arguments$column, data)
  ax <- eval(arguments$axis, data)

  # evaluated factors
  a<-reorder(with(data, ax), 
             with(data, col))

  #new_data
  df<-cbind.data.frame(data)
  # define new var
  within(df, 
         do.call("<-",list(paste0(as.character(arguments$axis),"_o"), a)))
}

Bây giờ, với chức năng này, bạn có thể vẽ tương tác với ggplot2, như thế này:

ggplot(order_axis(df, AXIS_X, COLUMN_Y), 
       aes(x = AXIS_X_o, y = COLUMN_Y)) +
        geom_bar(stat = "identity")

Có thể thấy, order_axishàm tạo ra một khung dữ liệu khác với một cột mới có tên tương tự nhưng _oở cuối. Cột mới này có các cấp theo thứ tự tăng dần, vì vậy ggplot2 sẽ tự động vẽ đồ thị theo thứ tự đó.

Điều này hơi hạn chế (chỉ hoạt động cho các ký tự hoặc yếu tố và kết hợp số cột và theo thứ tự tăng dần) nhưng tôi vẫn thấy nó rất hữu ích cho âm mưu khi đang di chuyển.


Tôi đoán tôi không thấy lợi thế của việc này so với việc chỉ sử dụng reordertrực tiếp. Không ggplot(df, aes(x = reorder(AXIS_X, COLUMN_Y), y = COLUMN_Y)) + ...làm điều tương tự, về chính xác, và không có chức năng trợ giúp?
Gregor Thomas
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.