Plotting Multiple Lines on Graph for Different groups in ggplot - r

I am trying to edit a plot that I created in ggplot such that each facet shows 2 different lines overlapping (one for avg. actual run hours, one for avg. scheduled run hours) as well as display a legend to the right to indicate which line is actual vs. scheduled. I referenced the post here but was unable to get the solution to work in my case because I'm dealing with different columns that need to be overlapped, and not a group within one variable. Please note that the lines will be nearly identical in this case, but I have other use cases involving the same task where the lines will differ significantly - hence the request for help.
My data is listed below for reference:
structure(list(month_yr = c("2022-01", "2022-01", "2022-02",
"2022-02", "2022-03", "2022-03", "2022-04", "2022-04", "2022-05",
"2022-05", "2022-06", "2022-06", "2022-07", "2022-07", "2022-08",
"2022-08", "2022-09", "2022-09", "2022-10", "2022-10", "2022-11",
"2022-11", "2022-12", "2022-12", "2023-01", "2023-01", "2023-02",
"2023-02"), plant_name = c("plant_f", "plant_s", "plant_f", "plant_s",
"plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s",
"plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s",
"plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s",
"plant_f", "plant_s", "plant_f", "plant_s", "plant_f", "plant_s"
), avg_run_hours = c(15.0080608695652, 16.3453608247423, 14.7394112149533,
16.1025555555556, 14.9570175438596, 15.7327777777778, 17.0074257425743,
16.5604901960784, 16.989010989011, 16.3021296296296, 14.8100961538462,
15.8714516129032, 16.5552083333333, 15.3971568627451, 16.2258771929825,
14.2616279069767, 17.2556179775281, 14.3790350877193, 16.3594903846154,
15.5988617886179, 14.4050925925926, 15.9334920634921, 14.3455056179775,
16.6322935779817, 16.6958762886598, 17.1025714285714, 16.046875,
16.8408695652174), avg_sched_run_hours = c(15.0267043478261,
16.4351340206186, 15.0025140186916, 16.2041555555556, 14.8281578947368,
15.9119814814815, 17.1840099009901, 16.7646666666667, 17.0109340659341,
16.4446388888889, 14.7679615384615, 16.1768790322581, 16.3242083333333,
15.7033333333333, 16.343701754386, 14.5158139534884, 17.4342921348315,
14.5827280701754, 16.4562692307692, 15.4149105691057, 14.2729537037037,
16.1438253968254, 14.3073595505618, 16.7186330275229, 16.6436082474227,
17.0332952380952, 16.3137916666667, 16.9656739130435)), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -28L), groups = structure(list(
month_yr = c("2022-01", "2022-02", "2022-03", "2022-04",
"2022-05", "2022-06", "2022-07", "2022-08", "2022-09", "2022-10",
"2022-11", "2022-12", "2023-01", "2023-02"), .rows = structure(list(
1:2, 3:4, 5:6, 7:8, 9:10, 11:12, 13:14, 15:16, 17:18,
19:20, 21:22, 23:24, 25:26, 27:28), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -14L), .drop = TRUE))
Code I used to create the image below:
hours_by_plant <-
ggplot(so_run_hour_stats, aes(x=month_yr, y=avg_sched_run_hours, group=1)) + geom_point() +
geom_line(color="red") + xlab("Month of Year") + ylab("Avg Run Hours") +
ggtitle("Avg Plant Run Hours by Month from 01/2022 - 02/2023") + theme_classic() +
facet_wrap(~plant_name)
hours_by_plant <- hours_by_plant + theme(plot.title = element_text(hjust = 0.5))

This type of problems generally has to do with reshaping the data. The format should be the long format and the data is in wide format. See this post on how to reshape the data from wide to long format.
I also transform the dates into real date objects and edit the avg_* columns after pivoting.
You can set the x axis date breaks to different values if you want to, for instance, to 1 month.
suppressPackageStartupMessages({
library(dplyr)
library(tidyr)
library(ggplot2)
})
so_run_hour_stats %>%
pivot_longer(cols = starts_with("avg"), names_to = "Average") %>%
mutate(month_yr = as.Date(paste0(month_yr, "-01")),
Average = sub("avg_", "", Average),
Average = gsub("_", " ", Average)) %>%
ggplot(aes(month_yr, value, colour = Average)) +
geom_line() +
geom_point(color = "black") +
scale_x_date(date_breaks = "3 months", date_labels = "%Y-%m") +
scale_color_manual(values = c("red", "blue")) +
facet_wrap(~ plant_name) +
theme_classic() +
theme(axis.text.x = element_text(angle = 60, vjust = 1, hjust = 1))
Created on 2023-02-18 with reprex v2.0.2

Related

Changing boxplot width (measuring multiple categorical variables) for categorical conditions with missing data

As a preliminary disclaimer, I am still very new to R (this is the first analysis I've performed independently), and am hoping this is a reproducible example.
I have a dataset measuring the d.13.C and d.18.O values of various enamel samples through time and space. I want to represent trends within Families across space and time. I have a boxplot I generated in ggplot2 that does this, but I'm running into a few problems:
d %>%
mutate(across(Member, factor, levels = c("UpperBurgi", "KBS", "Okote"))) %>%
mutate(across(Dep_context, factor, levels = c("Lacustrine", "Deltaic", "Fluvial "))) %>%
ggplot(aes(x = Member, y = d.13.C)) +
geom_boxplot(aes(x = Member, y = d.13.C, col = Dep_context, fill = Dep_context), alpha = 0.5, lwd = 1) +
facet_wrap(~Family) +
scale_fill_brewer(palette = "Dark2") +
scale_color_brewer(palette = "Dark2") +
theme_bw()
It produces something like this:
Since my data is not evenly distributed (not every depositional context is represented in each geologic member in each family), the boxplots for each depositional environment are different. I would like them to all be the same width, regardless of if the data is present or not (e.g., equivalent to the size of the ones in Bovidae in the KBS Member).
I've tried messing around with width = in the geom_boxplot call, I've tried using theme() to change aspects of the grid, and I've tried the drop = FALSE call, but that didn't change anything. I've also tried faceting my member and depositional environment, but that did not look as appealing and seemed clunkier. Is there a way to accomplish this, or is faceting the way to go?
I provided my dataframe below. *note: it's a subset since otherwise, the output was too long.
dput(head(d))
structure(list(CA = c("6", "1", "104", "105", "6A", "6A"), Member = c("KBS",
"Okote", "KBS", "KBS", "KBS", "KBS"), Dep_context = c("Deltaic",
"Fluvial ", "Fluvial ", "Fluvial ", "Deltaic", "Deltaic"), Family = c("Equidae",
"Equidae", "Equidae", "Equidae", "Equidae", "Equidae"), Tribe = c("",
"", "", "", "", ""), Genus = c("Equus", "Equus", "Equus", "Equus",
"Equus", "Equus"), d.13.C = c(-0.3, -0.7, 0.7, -0.9, -0.1, -0.8
), d.18.O = c(0, 1.6, 4, 2.6, 1.8, 0.2), Age.range = c("1.87-1.56",
"1.56-1.38", "1.87-1.56", "1.87-1.56", "1.87-1.56", "1.87-1.56"
)), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"
))
You could use position_dodge2 with preserve = "single" to keep the boxplot width the same across different groups like this:
library(ggplot2)
library(dplyr)
d %>%
mutate(across(Member, factor, levels = c("UpperBurgi", "KBS", "Okote"))) %>%
mutate(across(Dep_context, factor, levels = c("Lacustrine", "Deltaic", "Fluvial "))) %>%
ggplot(aes(x = Member, y = d.13.C)) +
geom_boxplot(aes(x = Member, y = d.13.C, col = Dep_context, fill = Dep_context), alpha = 0.5, lwd = 1,
position = position_dodge2(preserve = "single")) +
facet_wrap(~Family) +
scale_fill_brewer(palette = "Dark2") +
scale_color_brewer(palette = "Dark2") +
theme_bw()
Created on 2023-02-08 with reprex v2.0.2

Combining Text_Grob with ggplot via grid_arrange - delete Text_grob-Margins

I have been trying to merge a TextGrob with a ggplot for some time. Unfortunately, the TextGrob always creates a certain distance to the plot, which I do not want.
The whole thing becomes a bit clearer when looking at the current result:
The goal is to have the "Lennart" directly on the plot, as a kind of artificial axis label.
The current code looks like this: (I have adjusted the formatting somewhat, but the essentials should be recognisable)
png("PNGZwischenspeicher2.png", bg = "transparent", width = 2500, height = 1000)
p <- ggplot(DBE3, aes(x = reorder(emoji, n), y = n,reorder(emoji,-n)))+
theme(plot.margin = margin(0,0,0,0, "pt"))+
geom_col(alpha = 0.2, width = 0.2)+
coord_flip()+
theme(axis.title.y = element_blank())+
scale_fill_manual(values=c("transparent", "transparent", "transparent"))+
scale_y_continuous(expand = expansion(mult = c(0.00, .5)))
print(p)
dev.off()
img2 <- readPNG("PNGZwischenspeicher2.png")
PE2 <- rasterGrob(img2)
Header2 <- textGrob("Lennart", rot = 90, gp = gpar(fontsize = 12, fontface = 'plain'))
grid.arrange(Header2, PE2, nrow = 1)
Don't ask why it is necessary to edit the plot via the png-workaround, the current script doesn't allow it otherwise :D
If anyone knows a way to remove the space between the text_grob and the plot (or png), I would be very grateful.
My approach would be to adjust the size of the text_grob, but unfortunately I haven't found a working way to do this yet.
Thank you very much and have a nice evening!
Data needed for recreation:
dput(DBE3)
structure(list(author = structure(c(1L, 1L, 1L), .Label = c("Lennart",
"Toni Janina", "Toni"), class = "factor"), emoji = c("<U+0001F607>",
"<U+0001F64F>", "<U+0001F605>"), n = c(90L, 47L, 30L), name = c("smiling face with halo",
"folded hands", "grinning face with sweat"), hex_runes = c("1F607",
"1F64F", "1F605"), hex_runes1 = c("1F607", "1F64F", "1F605"),
emoji_url = c("https://abs.twimg.com/emoji/v2/72x72/1f607.png",
"https://abs.twimg.com/emoji/v2/72x72/1f64f.png", "https://abs.twimg.com/emoji/v2/72x72/1f605.png"
)), row.names = c(NA, -3L), groups = structure(list(author = structure(1L, .Label = c("Lennart",
"Toni Janina", "Toni"), class = "factor"), .rows = structure(list(
1:3), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr",
"list"))), row.names = c(NA, -1L), class = c("tbl_df", "tbl",
"data.frame"), .drop = TRUE), class = c("grouped_df", "tbl_df",
"tbl", "data.frame"))
Here is a simpler example that shows how to add a textGrob to a ggplot with {ggpp} (or {ggpmisc}). This could be also done with geom_text() but I guess you have something more complicated as the actual problem. This code can be used with any grob including bitmaps.
library(ggpp)
#> Loading required package: ggplot2
#>
#> Attaching package: 'ggpp'
#> The following object is masked from 'package:ggplot2':
#>
#> annotate
library(grid)
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
annotate(geom = "grob", x = 5, y = 40,
label = textGrob("Lennart", rot = 90, gp = gpar(fontsize = 12, fontface = 'plain')))
Created on 2021-07-29 by the reprex package (v2.0.0)

Adding dates to x-axis in time series plot [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have the following code:
library(ggplot2)
library(fpp2)
library(tidyverse)
library(tidyr)
library(lubridate)
library(writexl)
library(plyr)
library(forecast)
Sales171819 <- SalesNL[SalesNL$TransactionDate >= "2017-01-01" & SalesNL$TransactionDate <= "2019-12-31",]
#create time series
myts <- ts(Sales171819[,2],start = decimal_date(as.Date("2017-05-01")), frequency = 365)
#plot time series
view(myts)
autoplot(myts) + ggtitle("TAF Sales NL 2017/2018")+
ylab("SalesQty") + xlab("days")
# seasonal plot sales
ggseasonplot(myts) + ggtitle("Sales Per Dag")+
ylab("Sales") + xlab("Days")
I would like to plot the actual dates to the autoplot and ggseasonplot on the x axis, instead of day 1, 2, 3... etc. I would also like to highlight points in the plots with the actual dates. How can I edit my code so I can get this done?
The data looks like this:
TransactionDate NetSalesQty
1 2017-05-01 1221
2 2017-05-02 1275
3 2017-05-03 1198
4 2017-05-04 1792
5 2017-05-05 1842
6 2017-05-06 1183
structure(list(TransactionDate = structure(c(17287, 17288, 17289,
17290, 17291, 17292), class = "Date"), NetSalesQty = c(1221,
1293, 1525, 1475, 1854, 2189)), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))
Thanks in advance.
Well, I was not able to make autoplot() work with the myts object but based on the ylab() and xlab(), I made this plot:
Of course you can add geom_line() or others to make it look as you expect.
The code:
library(ggplot2)
SalesNL <- structure(list(TransactionDate = structure(c(17287, 17288, 17289,
17290, 17291, 17292), class = "Date"), NetSalesQty = c(1221,
1293, 1525, 1475, 1854, 2189)), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))
Sales171819 <- SalesNL[SalesNL$TransactionDate >= "2017-01-01" & SalesNL$TransactionDate <= "2019-12-31",]
ggplot(data = Sales171819,
aes(x = TransactionDate,
y = NetSalesQty,
color = ifelse(TransactionDate %in% as.Date(c("2017-05-02", "2017-05-04")), "outstanding", "normal")
)
) +
geom_point() +
scale_x_date(name = "Days",
# date_breaks = "1 day", # uncheck to get all labels
breaks = as.Date(c("2017-05-02", "2017-05-04"))) + # just pass a vector with dates you want to highlight
scale_y_continuous(name = "Sales") +
scale_color_manual(name = "highlights",
values = c("outstanding" = "red", "normal" = "black"))
You can also do it the other way around, with a color based on the y value:
ggplot(data = Sales171819,
aes(x = TransactionDate,
y = NetSalesQty,
color = ifelse(
NetSalesQty >= 1500,
"outstanding", # name for the legend and the choice of the color, see scale_color_manual
"normal") # name for the legend and the choice of the color, see scale_color_manual
)) +
geom_point() +
scale_x_date(name = "Days",
# date_breaks = "1 day",
breaks = Sales171819[Sales171819$NetSalesQty >= 1500, 1]$TransactionDate) +
scale_y_continuous(name = "Sales") +
scale_color_manual(name = "highlights",
values = c("outstanding" = "red", "normal" = "black"))
Output:

r: Inserting ggtexttable() inside a ggplot graph

I'm trying to insert a table that I created using the ggtexttable() function from the ggpubr package inside the plotting boundary of my ggplot plot. However, I keep getting this error:
Error in as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors) :
cannot coerce class "c("gg", "ggplot")" to a data.frame
I don't understand why I am getting error but I have a feeling it has to do with that I have dates on my x-axis? I would appreciate any feedback to fix this issue! Thanks!
Data:
HUC_df1 <- structure(list(charnam = c("Total dissolved solids", "Total dissolved solids",
"Total dissolved solids"), stdate = structure(c(11297, 11296,
11298), class = "Date"), val = c(439, 437, 510), HUC14 = c("HUC02030104020030",
"HUC02030104020030", "HUC02030104020030")), .Names = c("charnam",
"stdate", "val", "HUC14"), row.names = c(NA, -3L), class = c("tbl_df",
"tbl", "data.frame"))
HUC1_count<-structure(list(year = "2000", n_greater = 1L, percentage = 33.33,
n = 3L), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-1L), .Names = c("year", "n_greater", "percentage", "n"))
Code:
library(ggpubr)
library(ggplot2)
theme_graphs<- theme_linedraw()+
theme(plot.title=element_text(size=15, face="bold",vjust=0.5,hjust = 0.5),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
plot.background = element_blank(),
panel.background = element_blank(),
legend.position = c(0.5, 0.2),
legend.background = element_blank(),
legend.text=element_text(size=10, face="bold"))
HUC1_table<-ggtexttable(HUC1_count,
theme = ttheme("classic"),rows=NULL,
cols=c("Year","Number of Samples\n>500",
"Percent of Samples\n>500","Total Samples"))
HUC1<-ggplot(data = HUC_df1, aes(x =stdate, y = val)) +
geom_point()+
geom_hline(aes(yintercept = 500,color="red"),size=1.3)+
scale_y_continuous(expand = c(0, 0), limits = c(0))+
coord_cartesian(ylim = c(0, 700))+
scale_x_date(date_labels ="%b%Y")+
ggtitle("Elizabeth R (below Elizabeth CORP BDY) (HUC02030104020030)\nTDS Concentration (mg/L);1997-2018") +
xlab("Year") + ylab(" TDS Concentration (mg/L)")+
scale_color_manual("",
values = c("red"),
labels=c("Freshwater Aquatic Life Criteria for TDS = 500 mg/L"))+
theme_graphs+
theme(legend.position =c(0.5, -0.098))
HUC1<-HUC1+annotation_custom(tableGrob(HUC1_table), xmin=1.5,
xmax=1.8,
ymin=200, ymax=300)
I see two problems here. First, tableGrob is a function for creating a grob from a data.frame. But you've already created your table do you don't need that function. But ggtexttable returns a ggplot object, but you need a grob, so you need ot use ggplotGrob to turn that ggplot object into something you can use with annotation_custom.
The second problem is the range you specific for your x values. Since your data is formatted as a Date vector, those values are stored as the number of days since 1970-01-01 so values of 1.5 and 1.8 are way outside the range of what you are actually plotting. You can see your actual range with
range(as.numeric((HUC_df1$stdate)))
# [1] 11296 11298
So fixing those two problems, what you want for the example is
HUC1+annotation_custom(ggplotGrob(HUC1_table), xmin=11296,
xmax=11298,
ymin=200, ymax=300)

Ordering of items within a stacked geom_bar

I want, for reasons which seems good to me, to plot a stacked bar chart, with the bars in a specific, data dependent order. For reasons which are obscure to me, it does not seem to work. Specifically, while I can readily arrange the rows of my dataframe in the right order, and make the column of names identifying the bars an ordered factor, so getting the bars in the order I desire, the graph does not list the columns of the dataframe in the order I desire.
An example
tab <- structure(list(Item = c("Personal", "Peripheral", "Communication", "Multimedia", "Office", "Social Media"), `Not at all` = c(3.205128, 18.709677, 5.844156, 31.578947, 20.666667, 25.827815), Somewhat = c(30.76923, 23.87097, 24.67532, 18.42105, 30, 16.55629), `Don't know` = c(0.6410256, 2.5806452, 1.9480519, 11.1842105, 2.6666667, 5.9602649), Confident = c(32.69231, 29.67742, 33.11688, 17.10526, 23.33333, 27.15232), `Very confident` = c(32.69231, 25.16129, 34.41558, 21.71053, 23.33333, 24.50331)), .Names = c("Item", "Not at all", "Somewhat", "Don't know", "Confident", "Very confident"), row.names = c(NA, -6L), class = "data.frame")
Title <- 'Plot title'
ResponseLevels <- c("Not at all", "Somewhat", "Don't know", "Confident", "Very confident") # Labels for bars
pal.1 <- brewer.pal(category, 'BrBG') # Colours
tab <- tab %>% arrange(.[,2]) # Sort by first columns of responses
tab$Item <- factor(tab$Item, levels = tab$Item[order(tab[,2])], ordered = TRUE) # Reorder factor levels
tab.m <- melt(tab, id = 'Item')
tab.m$col <- rep(pal.1, each = items) # Set colours
g <- ggplot(data = tab.m, aes(x = Item, y = value, fill = col)) +
geom_bar(position = "stack", stat = "identity", aes(group = variable)) +
coord_flip() +
scale_fill_identity("Percent", labels = ResponseLevels,
breaks = pal.1, guide = "legend") +
labs(title = Title, y = "", x = "") +
theme(plot.title = element_text(size = 14, hjust = 0.5)) +
theme(axis.text.y = element_text(size = 16,hjust = 0)) +
theme(legend.position = "bottom")
g
The stacked pieces of the bars run from right to left, from 'Not at all' to 'Very confident'. The items are in the correct order, from 'Multimedia' to 'Personal', ordered by the proportion of those who said 'Not at all' to each item.
What I want to get is this graph with the responses ordered the other way, the same way as the legend, that is from 'Not at all' on the left, to 'Very confident' on the right. I cannot figure out how this ordering is set, nor how to change it.
I've read through the 'similar questions', but can see no answer to this specific query. Suggestions, using ggplot, not base R graphics, welcome.
Ok, building on the useful, and much appreciated answer from allstaire, I try the following
library(tidyverse)
tab <- structure(list(Item = c("Personal", "Peripheral", "Communication", "Multimedia", "Office", "Social Media"), `Not at all` = c(3.205128, 18.709677, 5.844156, 31.578947, 20.666667, 25.827815), Somewhat = c(30.76923, 23.87097, 24.67532, 18.42105, 30, 16.55629), `Don't know` = c(0.6410256, 2.5806452, 1.9480519, 11.1842105, 2.6666667, 5.9602649), Confident = c(32.69231, 29.67742, 33.11688, 17.10526, 23.33333, 27.15232), `Very confident` = c(32.69231, 25.16129, 34.41558, 21.71053, 23.33333, 24.50331)), .Names = c("Item", "Not at all", "Somewhat", "Don't know", "Confident", "Very confident"), row.names = c(NA, -6L), class = "data.frame")
tab <- tab %>% select(1,6,5,4,3,2,1) ## Re-order the columns of tab
tab.m <- tab %>% arrange(`Not at all`) %>%
mutate(Item = factor(Item, levels = Item[order(`Not at all`)])) %>%
gather(variable, value, -Item, factor_key = TRUE)
ggplot(data = tab.m, aes(x = Item, y = value, fill = variable)) +
geom_col() +
coord_flip() +
scale_fill_brewer("Percent", type = 'cat', palette = 'BrBG',
guide = guide_legend(reverse = TRUE)) +
labs(title = 'Plot title', y = NULL, x = NULL) +
theme(legend.position = "bottom")
And this is exactly the graph I want, so my pressing problem is solved.
However, if I say instead
ggplot(data = tab.m, aes(x = Item, y = value, fill = variable)) +
geom_col() +
coord_flip() +
scale_fill_brewer("Percent", type = 'cat', palette = 'BrBG',
guide = guide_legend(reverse = FALSE)) +
labs(title = 'Plot title', y = NULL, x = NULL) +
theme(legend.position = "bottom")
The picture I get is this
Here the body of the chart is correct, but the legend is going in the wrong direction.
This solves my problem, but does not quite answer my question. I start with a dataframe, and to get what I want I have to reverse the order of the data columns, and reverse the guide legend. This evidently works, but it's perverse.
So, how does a stacked bar chart decide in what order to present the stacked items? It's clearly related to their order in the melted dataset, but simply changing the order leaves the legend going in the wrong direction. Looking at the melted dataset, tab.m, from top to bottom, the responses are in the order 'Very confident' to 'Not at all', but the default legend is the reverse order 'Not at all' to 'Very confident'.
If you pass guide_legend instead of just a string, you can set its reverse parameter to TRUE. Simplifying a bit,
library(tidyverse)
tab <- structure(list(Item = c("Personal", "Peripheral", "Communication", "Multimedia", "Office", "Social Media"), `Not at all` = c(3.205128, 18.709677, 5.844156, 31.578947, 20.666667, 25.827815), Somewhat = c(30.76923, 23.87097, 24.67532, 18.42105, 30, 16.55629), `Don't know` = c(0.6410256, 2.5806452, 1.9480519, 11.1842105, 2.6666667, 5.9602649), Confident = c(32.69231, 29.67742, 33.11688, 17.10526, 23.33333, 27.15232), `Very confident` = c(32.69231, 25.16129, 34.41558, 21.71053, 23.33333, 24.50331)), .Names = c("Item", "Not at all", "Somewhat", "Don't know", "Confident", "Very confident"), row.names = c(NA, -6L), class = "data.frame")
tab.m <- tab %>% arrange(`Not at all`) %>%
mutate(Item = factor(Item, levels = Item[order(`Not at all`)])) %>%
gather(variable, value, -Item, factor_key = TRUE)
ggplot(data = tab.m, aes(x = Item, y = value, fill = variable)) +
geom_col() +
coord_flip() +
scale_fill_brewer("Percent", palette = 'BrBG',
guide = guide_legend(reverse = TRUE)) +
labs(title = 'Plot title', y = NULL, x = NULL) +
theme(legend.position = "bottom")
For the edit:
Bar order is determined by factor level order, which in the above is determined by column order due to the use of gather to create the factor, thoughcoord_flip is making it less obvious. It's easy to reverse level order with levels<- or by reassembling the factor, though. To keep the colors with the same levels, pass direction = -1 to scale_fill_brewer to reverse their order, as well.
tab.m <- tab %>% arrange(`Not at all`) %>%
mutate(Item = factor(Item, levels = Item[order(`Not at all`)])) %>%
gather(variable, value, -Item, factor_key = TRUE) %>%
mutate(variable = factor(variable, levels = rev(levels(variable)), ordered = TRUE))
ggplot(data = tab.m, aes(x = Item, y = value, fill = variable)) +
geom_col() +
coord_flip() +
scale_fill_brewer("Percent", palette = 'BrBG', direction = -1,
guide = guide_legend(reverse = TRUE)) +
labs(title = 'Plot title', y = NULL, x = NULL) +
theme(legend.position = "bottom")

Resources