Robert Tan
Robert Tan

Reputation: 674

Reorder() ggplot2 scatterplot X axis using a subset's Y value

Problem

I've looked at numerous SO questions/R Studio blogs to solve the problem but nothing has helped thus far. I tried using various functions in the reorder() function, creating and using a wide dataset.

https://rstudio-pubs-static.s3.amazonaws.com/7433_4537ea5073dc4162950abb715f513469.html

reorder x-axis variables by sorting a subset of the data

How do I sort a dataframe by the average of subsets of one of the rows?

Output Goal

Each X point has 3 Y values - one is a benchmark. To show how the 2 other points perform, I need to order the benchmark in descending fashion to create a graph like so (red being benchmark):

enter image description here

The above chart is simulated to show the goal. Please ignore the few of the red outlier dots.

Current method

sample.chart <-
  ggplot(sample.data, aes(
    x = reorder(store, -scaling),
    y = scaling,
    color=version
  )) +
  geom_point(alpha = 0.7) +
  theme(
    axis.text.x = element_blank()
  )

How would I be able to 'target' a specific subset to order the chart by?

Data str

> str(sample.data)

Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   60 obs. of  3 variables:
 $ store  : int  1 2 3 4 5 6 7 8 9 10 ...
 $ scaling: num  3.67 17.5 51 7.6 49 ...
 $ version: chr  "test.1" "test.1" "test.1" "test.1" ...

Data

> dput(sample.data)

structure(list(store = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 
10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 1L, 2L, 
3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 
17L, 18L, 19L, 20L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 
11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L), scaling = c(3.66666666666667, 
17.5, 51, 7.6, 49, 0.333333333333333, 7.25, 13, 1.66666666666667, 
9.73333333333333, 0.307692307692308, 0.74468085106383, 5, 1.27272727272727, 
0.259259259259259, 0.866666666666667, 2.625, 1.58333333333333, 
2.71428571428571, 0.625, 5.5, 35, 51, 9.5, 49, 3, 4.83333333333333, 
8.66666666666667, 3.33333333333333, 4.17142857142857, 0.666666666666667, 
2.91666666666667, 1.42857142857143, 2.8, 0.424242424242424, 0.8125, 
1.82608695652174, 1.72727272727273, 2.375, 0.571428571428571, 
66, 62.78461538, 56.1, 53.9, 49.5, 47.3, 39.1, 39.05, 37.2, 30.8, 
29.7, 29.15, 28.6, 23.61333333, 20.8, 19.25, 18.61538462, 17.74666667, 
17.11111111, 16.8), version = c("test.1", "test.1", "test.1", 
"test.1", "test.1", "test.1", "test.1", "test.1", "test.1", "test.1", 
"test.1", "test.1", "test.1", "test.1", "test.1", "test.1", "test.1", 
"test.1", "test.1", "test.1", "test.2", "test.2", "test.2", "test.2", 
"test.2", "test.2", "test.2", "test.2", "test.2", "test.2", "test.2", 
"test.2", "test.2", "test.2", "test.2", "test.2", "test.2", "test.2", 
"test.2", "test.2", "benchmark", "benchmark", "benchmark", "benchmark", 
"benchmark", "benchmark", "benchmark", "benchmark", "benchmark", 
"benchmark", "benchmark", "benchmark", "benchmark", "benchmark", 
"benchmark", "benchmark", "benchmark", "benchmark", "benchmark", 
"benchmark")), .Names = c("store", "scaling", "version"), row.names = c(NA, 
-60L), class = c("tbl_df", "tbl", "data.frame"))

Upvotes: 1

Views: 2475

Answers (2)

David Klotz
David Klotz

Reputation: 2431

Regardless of how you order the x-axis values, since you keep them as numeric values, ggplot will order them numerically.  Instead, you need to turn them into factors, ordered by descending order of the y-value.  Factors are technically stored with ordinal values, so ggplot will order the points by those new integer indices instead:

library(dplyr)
library(forcats)

sample.data <- sample.data %>% 
    arrange(version, desc(scaling)) %>% #benchmark comes first alphabetically, so it will use all of those values first for sorting
    mutate(store = as_factor(as.character(store)))

ggplot(sample.data, aes(
    x = store,
    y = scaling,
    color=version
  )) +
  geom_point(alpha = 0.7) +
  theme(
    axis.text.x = element_blank()
  )

Upvotes: 0

MrFlick
MrFlick

Reputation: 206411

How about this

ggplot(sample.data, aes(
  x = reorder(store, -scaling*(version=="benchmark"), max),
  y = scaling,
  color=version
)) +
  geom_point(alpha = 0.7) +
  theme(
    axis.text.x = element_blank()
  )

Here we multiply the non-benchmark scores by 0 (FALSE ~= 0) and take the max to reorder each group based only on the benchmark score.

enter image description here

Upvotes: 1

Related Questions