simoncolumbus
simoncolumbus

Reputation: 566

Bar plot with negative and positive values centered on a non-zero value

I am trying to create a bar graph of odds ratios. Interpretationally, they are centered around 1, not 0. Therefore, I would like to have a bar graph where values below 1 are "negative" and values above 1 are "positive" (i.e., a graph of distance from 1).

Effectively, the graph should look like the following plot except that the labels on the y axis should be centered around 1, not 0.

the plot

I would like to create this graph not be relabeling of the y axis, but by actually centering it around 1. Is this possible; and if so, how?

Code to create the example graph:

data <- matrix(c(rnorm(5, 1, .5)), 5, 1)
data <- as.data.frame(data)
data[,2] <- data[,1] - .1
data[,3] <- data[,1] + .1
data <- cbind(c(letters[1:5]), data)
names(data) <- c("Category", "OR", "Lower", "Upper")

data.zero <- cbind("Category"=data[,1], data[,2:4] - 1)

require(ggplot2)
ggplot() + 
  geom_bar(data = data.zero, aes(x=Category, y=OR, fill=Category), stat = "identity") +
  scale_fill_brewer(type = "seq", palette = 1) +  
  geom_errorbar(aes(x=Category, y=OR, ymin=Lower, ymax=Upper), 
            width=.1, position=position_dodge(), data=data.zero)

Upvotes: 2

Views: 7153

Answers (2)

alko989
alko989

Reputation: 7908

If I understand your question correctly you don't want to relabel the y-axis, you want it centered to 1.

## Find the minimum and maximum y
mi <- min(data.zero$Lower)
ma <- max(data.zero$Upper)

Now I check which distance is greater, from 1 to mi or from 1 to ma. I set the ylim by increasing the smaller distance from 1.

if(1 - mi > ma - 1) { 
    newylim <- c(mi  , 2 - mi)  ## Lower limit remains same, Upper limit is increased
} else { 
    newylim <- c(2 - ma, ma)    ## Upper limit remains same, Lower limit is decreased
}

then you can plot adding:

+ ylim(newylim)

The plot with your code is in the left and adding the ylim in the right.

enter image description here

Hope it helps,

alex

Upvotes: 0

hvollmeier
hvollmeier

Reputation: 2986

Define a simple function to add 1, like so:

plus1_formatter <- function(x) {x +1}

and than add the string

+ scale_y_continuous(labels=plus1_formatter)

to your ggplot command above.

to make it reproducible set seed(123)

before: before changing the labels

after: enter image description here

Upvotes: 1

Related Questions