user3390169
user3390169

Reputation: 1045

R ggplot2 bar chart change color of specific bars

I have this dataframe called earningsCont that I will use to make a stacked bar chart:

                       Total     Ghost
JPYUSD          -39837298.85         0
GBPUSD           -1981571.03 -39837299
EURUSD           -1251394.07 -41818870
MXNUSD            -498204.15 -43070264
NZDUSD            -333466.88 -43568468
PLNUSD            -215056.56 -43901935
CNYUSD            -143457.92 -44116992
AUDUSD            -130047.28 -44260449
CADUSD             -94396.57 -44390497
CHFUSD             -46730.39 -44484893
HKDUSD             -24084.79 -44531624
BRLUSD                  0.00 -44555709
Diversification  -4276539.06 -40279169
Portfolio       -40279169.44         0

I then melt it to look like this:

              Var1  Var2        value
1           JPYUSD Total -39837298.85
2           GBPUSD Total  -1981571.03
3           EURUSD Total  -1251394.07
4           MXNUSD Total   -498204.15
5           NZDUSD Total   -333466.88
6           PLNUSD Total   -215056.56
7           CNYUSD Total   -143457.92
8           AUDUSD Total   -130047.28
9           CADUSD Total    -94396.57
10          CHFUSD Total    -46730.39
11          HKDUSD Total    -24084.79
12          BRLUSD Total         0.00
13 Diversification Total  -4276539.06
14       Portfolio Total -40279169.44
15          JPYUSD Ghost         0.00
16          GBPUSD Ghost -39837298.85
17          EURUSD Ghost -41818869.88
18          MXNUSD Ghost -43070263.95
19          NZDUSD Ghost -43568468.11
20          PLNUSD Ghost -43901934.98
21          CNYUSD Ghost -44116991.55
22          AUDUSD Ghost -44260449.46
23          CADUSD Ghost -44390496.75
24          CHFUSD Ghost -44484893.32
25          HKDUSD Ghost -44531623.72
26          BRLUSD Ghost -44555708.50
27 Diversification Ghost -40279169.44
28       Portfolio Ghost         0.00

I use this code to make the chart:

ggplot(data=earningsCont, aes(x=Var1, y=value, fill=Var2, order=-as.numeric(Var2))) + geom_bar(stat="identity")+
    theme_bw() + theme(panel.border = element_blank(), panel.grid.major = element_blank(), 
    panel.grid.minor = element_blank(), axis.line = element_line(colour = "black")) +
    labs(x="", y="") + 
    scale_y_continuous(labels = comma) +
    ggtitle("Earnings at Risk:  Unhedged (USD)") +
    scale_fill_manual(values = c(wfGold, wfWhite))+ guides(fill=FALSE)

That makes it look like the attached picture. As you can see, one of the sets of columns, "Ghost," is white so you can't see it. The other is all gold. I just want to change the last two gold columns to colors that I have defined as wfGreen and wfRed.grasph

Also, why do I have to melt it before I turn it into a bar chart? Is there now way to say series1=earningsCont$Total and series2=earningsCont$Ghost?

Upvotes: 0

Views: 1905

Answers (1)

Joe
Joe

Reputation: 3991

You're coloring your bars based on the value of Var2, which contains no information about whether the element is one of the last two columns ('Diversification' and 'Portfolio'). You need a grouping column in your dataframe which contains this information. You can add this manually, or using the following (clunky) code:

earningsConst.plot <- within(earningsConst, {
  Var3 <- ifelse(Var2 == "Ghost", "Ghost",
    ifelse(Var1 == "Diversification", "Div",
      ifelse(Var1 == "Portfolio", "Port",
        "Total")))
})

This should create a new dataframe identical to the last, but with a four-level coloring column Var3 to give to the fill aesthetic. You can tweak your original code to plot like this:

ggplot(data=earningsCont.plot, aes(x=Var1, y=value, fill=Var3, order=-as.numeric(Var2))) + geom_bar(stat="identity")+
    theme_bw() + theme(panel.border = element_blank(), panel.grid.major = element_blank(), 
    panel.grid.minor = element_blank(), axis.line = element_line(colour = "black")) +
    labs(x="", y="") + 
    scale_y_continuous(labels = comma) +
    ggtitle("Earnings at Risk:  Unhedged (USD)") +
    scale_fill_manual(values = c(wfGold, wfRed, wfWhite, wfGreen))+ guides(fill=FALSE)

Note that as you didn't dput your data I was unable to test this code (I opted not to manually type in your whole dataframe). While I'm farily certain that this should work, it's possible I've made a small mistake somewhere. If you find one, let me know- or better yet dput(earningsConst) so as to have an easily-reproducible example.

Upvotes: 2

Related Questions