R: ordering faces by value, not alphabetical order in ggplot2

A few weeks ago, I used ggplot2 to create a faceted graph in which faxes were ordered by the last value in a data frame. I had no serious problems until he switched to reordering, because I did not understand all the difficulties of orders, factors and levels. However, after an hour or two (or three) calls to SO messages, I got it working.

When I returned to the script today, it no longer worked, because now it sorts the faces alphabetically, and not according to the final value of the data frame. (I think that I initially “fixed” the problem during the mess on the R console and did not actually add a solution for the script.) Instead of spending a couple more hours this evening, I'm going to rush to SO charity.

Q. How can I sort faces by a given value, rather than alphabetically by the name of each face? Please note that the code below is an example; real data has several tens of elements.

The edited code below to reflect the additional input from @joran; faces are now sorted and filled accordingly. Successful mission.

# Version 3 require(ggplot2) ## NB This script assumes you have ggplot2 v0.90 require(scales) require(plyr) require(lubridate) require(reshape) set.seed(12345) monthsback <- 15 date <- as.Date(paste(year(now()),month(now()),"1",sep="-")) - months(monthsback) myitems <- data.frame(mydate=seq(as.Date(date), by="month", length.out=monthsback), aaa = runif(monthsback, min = 600, max = 800), bbb = runif(monthsback, min = 100, max = 200), ccc = runif(monthsback, min = 1400, max = 2000), ddd = runif(monthsback, min = 50, max = 120)) myitems <- melt(myitems, id = c('mydate')) change_from_start <- function(x) { (x - x[1]) / x[1] } myitems <- ddply(myitems, .(variable), transform, value = change_from_start(value)) myitems$mydate <- as.Date(myitems$mydate, format = "%Y-%m-%d") myvals <- myitems[myitems$mydate == myitems$mydate[nrow(myitems)],] # get values on which to sort facets myvals <- within(myvals, variable <- factor(variable, as.character(myvals[order(myvals$value, decreasing = T),]$variable),ordered = TRUE)) myitems <- within(myitems, variable <- factor(variable, as.character(myvals[order(myvals$value, decreasing = T),]$variable),ordered = TRUE)) print(levels(myitems$variable)) # check to see if ordering succeeded myitems$fill <- ifelse(myitems$variable == "ddd", "blue", "darkgreen") p <- ggplot(myitems, aes(y = value, x = mydate, group = variable)) + geom_rect(aes(xmin = as.Date(myitems$mydate[1]), xmax = Inf, fill = fill), ymin = -Inf, ymax = Inf) + scale_fill_manual(values = c("blue", "darkgreen")) + geom_line(colour = "black") + geom_text(data = myvals, aes(x = as.Date(myitems$mydate[1]) + 250, y = 0.2, label = sprintf("%1.1f%%", value * 100))) + facet_wrap( ~ variable, ncol = 2) + geom_hline(yintercept = 0, size = 0.6, linetype = "dotdash") + scale_y_continuous(label = percent_format()) + scale_x_date(expand = c(0,0), labels = date_format("%Y-%m"), breaks = date_breaks("year")) + xlab(NULL) + ylab(NULL) + opts(legend.position = "none") + opts(panel.grid.minor = theme_blank()) + opts() print(p) 

Image showing that facets are now sorted properly but that the fill is no longer working

+6
source share
2 answers

You have two problems:

  • A line that converts myitems$variable to a coefficient must specify ordered = TRUE to ensure that it is an ordered factor.

  • Your geom_text call uses a separate data frame, the corresponding variable of which is not a factor (or ordered), so it stomps myitems by the ordered character.

Transform both of them or ordered factors, and you should be fine.

+3
source

Facet are ordered in the same order as the variables in the original data.frame format.
Thus, as a basic hack, you can simply order the variable name when creating data.frame:

 myitems <- data.frame(mydate=seq(as.Date(date), by="month", length.out=monthsback), 'ccc' = runif(monthsback, min = 1400, max = 2000), 'aaa' = runif(monthsback, min = 600, max = 800), 'ddd' = runif(monthsback, min = 50, max = 120), 'bbb' = runif(monthsback, min = 100, max = 200) ) 

If you need to reorder at the end of the process then organizing () is best.

0
source

Source: https://habr.com/ru/post/910438/


All Articles