Change colours of particular bars in a bar chart

Solution 1:

Here's one strategy:

## Create a reproducible example
set.seed(5)
x <- cumsum(rnorm(50))

## Create a vector of colors selected based on whether x is <0 or >0  
## (FALSE + 1 -> 1 -> "blue";    TRUE + 1 -> 2 -> "red")
cols <- c("blue", "red")[(x > 0) + 1]  

## Pass the colors in to barplot()   
barplot(x, col = cols)

If you want more than two value-based colors, you can employ a similar strategy (using findInterval() in place of the simple logical test):

vals <- -4:4
breaks <- c(-Inf, -2, 2, Inf)
c("blue", "grey", "red")[findInterval(vals, vec=breaks)]
# [1] "blue" "blue" "grey" "grey" "grey" "grey" "red"  "red"  "red" 

enter image description here

Solution 2:

A ggplot2 solution using geom_bar with stat_identity.

library(ggplot2)
ggplot(dat, aes(x= seq_along(x), y = x)) + 
  geom_bar(stat = 'identity', aes(fill = x>0), position = 'dodge', col = 'transparent') + 
  theme_bw() + scale_fill_discrete(guide = 'none') + 
  labs(x = '', y = 'NAO Index')

enter image description here

scale_fill_discrete(guide = 'none') removes the legend, position = 'dodge' stops the warning that comes from the default position = 'stack'.

Solution 3:

One way is to index a vector of colours with a logical or factor variable (this is a common idiom in R.

set.seed(1)
NAO <- rnorm(40)
cols <- c("red","black")
pos <- NAO >= 0
barplot(NAO, col = cols[pos + 1], border = cols[pos + 1])

The trick here is pos:

> pos
 [1] FALSE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE
[11]  TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE
[21]  TRUE  TRUE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE
[31]  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE

which we coerce to numeric in the barplot() call:

> pos + 1
 [1] 1 2 1 2 2 1 2 2 2 1 2 2 1 1 2 1 1 2 2 2 2 2 2 1 2 1 1 1 1 2
[31] 2 1 2 1 1 1 1 1 2 2

The vector of 1s and 2s selects elements from the vector of colour cols, such that:

> cols[pos + 1]
 [1] "red"   "black" "red"   "black" "black" "red"   "black"
 [8] "black" "black" "red"   "black" "black" "red"   "red"  
[15] "black" "red"   "red"   "black" "black" "black" "black"
[22] "black" "black" "red"   "black" "red"   "red"   "red"  
[29] "red"   "black" "black" "red"   "black" "red"   "red"  
[36] "red"   "red"   "red"   "black" "black"

which is the colour passed on to each bar drawn.

In the code above I also set the border of the bars to the relevant colour, via argument border.

The resulting plot should look like this

enter image description here

Solution 4:

I found this page while looking for help on how to colour individual bars in a bar chart according to a factor. I couldn't find any other source of information but thanks to this page, came up with this:

cols <- ifelse(df$Country == "Greenland", "green","blue")

It then gets passed into barplot in the usual way as described above:

barplot(x, col = cols)