I am trying to plot two flows and one rainfall data in one graph. I have broke it up into top and bottom parts as shown in the following pic. Here I have two issues with this plots and spent ages but cannot solve it.
Why the observed flow always in black, even I have set it up as blue? Did I accidentally used some other arguments to overwrite it?
The most importantly is, how do I able to add a legend for the bottom plot? I tried many different codes but they don't seem to work for me.
x = data.frame(date = Date, rain = Obs_rain, obsflow = Obs_flow,simflow=Sim_flow)
g.top <- ggplot(x, aes(x = date, y = rain, ymin=0, ymax=rain)) +
geom_linerange() +
scale_y_continuous(trans = "reverse") +
theme_bw() +
theme(plot.margin = unit(c(1,5,-30,6),units="points"),
axis.title.y = element_text(vjust =0.3)) +
labs(x = "Date",y = "Rain(mm)")
g.bottom <- ggplot(x, aes(x = date, y = obsflow, ymin=0, ymax=obsflow), colour = "blue",size=0.5) +
geom_linerange() + #plot flow
geom_linerange(aes(y = simflow, ymin=0, ymax=simflow), colour = "red", size =0.5)+
labs(x = "Date", y = "River flow (ML/day)") +
theme_classic() +
theme(plot.background = element_rect(fill = "transparent"),
plot.margin = unit(c(2,0,1,1),units="lines"))
grid.arrange(g.top,g.bottom, heights = c(1/5, 4/5))
Update:
I have resolved the issue with blue line colour. I accidently put arguments in the wrong place. But I'm still struggling with the legend.
g.bottom <- ggplot(x, aes(x = date, y = obsflow, ymin=0, ymax=obsflow)) +
geom_linerange(colour = "blue",size=0.5) + #plot flow
As an explanation of what #pierre means... turn your data from "wide" to "long" format using reshape2::melt, so that the flow type for each date is in one column flow_type, and the value is another (flow_val). Then you specify flow_type as the grouping variable with which to assign colour:
require(reshape2)
x.melted <- melt(x, id.vars = c("date", "rain"), variable.name="flow_type",
value.name="flow_val")
g.bottom <- ggplot(x.melted, aes(x = date),size=0.5) +
geom_linerange(aes(ymin=0, ymax=flow_val, colour=flow_type)) + #plot flow
labs(x = "Date", y = "River flow (ML/day)") +
theme_classic() +
theme(plot.background = element_rect(fill = "transparent"),
plot.margin = unit(c(2,0,1,1),units="lines"),
legend.position="bottom") +
scale_colour_manual(guide = guide_legend(title = "Flow Type"),
values = c("obsflow"="blue", "simflow"="red"))
Related
hist <- ggplot(df, aes(x = A,fill = ("red"))) +
geom_bar() +
theme_minimal() +
ggtitle("Treatment") + theme(legend.position = "bottom", plot.title = element_text(hjust=0.5), text = element_text(size = 20)) +
scale_fill_manual("A", values = c("0" = "dodgerblue4", "1" = "chocolate"))
hist
I need help regarding setting the colors of the boxplots from the ggplot2 package which I am learning right now. I want the left one to be in the blue color and the right one in the other color. But unfortunately I cannot figure out how to set these instead this code just sets the right colors in the Legend and leaves the boxes unchanged?!
Like Rene said it is a bit hard to help while not seeing the dataset.
Looking at the given code your A contains two values you want to color individually
define a vector containing those two values:
df_colors <- c("0" , "1")
hist <- ggplot(df, aes(x = A, fill = df_colors )) +
geom_bar() +
theme_minimal() +
ggtitle("Treatment") + theme(legend.position = "bottom", plot.title = element_text(hjust=0.5), text = element_text(size = 20)) +
scale_fill_manual("A", values = c("0" = "dodgerblue4", "1" = "chocolate"))
Not enough code for me to know exactly what you're doing but I think if you remove:
mapping = aes(fill = "red")
it will solve your problem. A reprex would help others better understand your problem. I think instead you might need something like:
ggplot(data = your_data) +
geom_bar(mapping = aes(x = variable_1, y = variable_2, fill = variable_3), position = "dodge")
I am using the windrose function posted here: Wind rose with ggplot (R)?
I need to have the percents on the figure showing on the individual lines (rather than on the left side), but so far I have not been able to figure out how. (see figure below for depiction of goal)
Here is the code that makes the figure:
p.windrose <- ggplot(data = data,
aes(x = dir.binned,y = (..count..)/sum(..count..),
fill = spd.binned)) +
geom_bar()+
scale_y_continuous(breaks = ybreaks.prct,labels=percent)+
ylab("")+
scale_x_discrete(drop = FALSE,
labels = waiver()) +
xlab("")+
coord_polar(start = -((dirres/2)/360) * 2*pi) +
scale_fill_manual(name = "Wind Speed (m/s)",
values = spd.colors,
drop = FALSE)+
theme_bw(base_size = 12, base_family = "Helvetica")
I marked up the figure I have so far with what I am trying to do! It'd be neat if the labels either auto-picked the location with the least wind in that direction, or if it had a tag for the placement so that it could be changed.
I tried using geom_text, but I get an error saying that "aesthetics must be valid data columns".
Thanks for your help!
One of the things you could do is to make an extra data.frame that you use for the labels. Since the data isn't available from your question, I'll illustrate with mock data below:
library(ggplot2)
# Mock data
df <- data.frame(
x = 1:360,
y = runif(360, 0, 0.20)
)
labels <- data.frame(
x = 90,
y = scales::extended_breaks()(range(df$y))
)
ggplot(data = df,
aes(x = as.factor(x), y = y)) +
geom_point() +
geom_text(data = labels,
aes(label = scales::percent(y, 1))) +
scale_x_discrete(breaks = seq(0, 1, length.out = 9) * 360) +
coord_polar() +
theme(axis.ticks.y = element_blank(), # Disables default y-axis
axis.text.y = element_blank())
#teunbrand answer got me very close! I wanted to add the code I used to get everything just right in case anyone in the future has a similar problem.
# Create the labels:
x_location <- pi # x location of the labels
# Get the percentage
T_data <- data %>%
dplyr::group_by(dir.binned) %>%
dplyr::summarise(count= n()) %>%
dplyr::mutate(y = count/sum(count))
labels <- data.frame(x = x_location,
y = scales::extended_breaks()(range(T_data$y)))
# Create figure
p.windrose <- ggplot() +
geom_bar(data = data,
aes(x = dir.binned, y = (..count..)/sum(..count..),
fill = spd.binned))+
geom_text(data = labels,
aes(x=x, y=y, label = scales::percent(y, 1))) +
scale_y_continuous(breaks = waiver(),labels=NULL)+
scale_x_discrete(drop = FALSE,
labels = waiver()) +
ylab("")+xlab("")+
coord_polar(start = -((dirres/2)/360) * 2*pi) +
scale_fill_manual(name = "Wind Speed (m/s)",
values = spd.colors,
drop = FALSE)+
theme_bw(base_size = 12, base_family = "Helvetica") +
theme(axis.ticks.y = element_blank(), # Disables default y-axis
axis.text.y = element_blank())
I have made a ggplot line plot that uses two uses two sets of time series data and looks as it should as a static plot. Script and plot below:
p_curve <- ggplot(df, aes(x = Var1, y = Var2)) +
geom_path(size = 1, colour = "red") +
geom_path(x = Var3, y = Var4, size = 1, colour = "blue") +
geom_vline(xintercept = 0) +
geom_hline(yintercept = Var2[1]) +
xlim(c(min(df$Var1, df$Var3)), c(max(df$Var1, df$Var3))) +
ylim(c(min(df$Var2, df$Var4)), c(max(df$Var2, df$Var4))) +
theme_classic() +
labs(x = "Variable", y = "Other Variable", title = "Variable x Variable Curve") +
theme(plot.title = element_text(hjust = 0.5),
panel.border = element_rect(colour = "black", fill = NA, size = 0.5))
The plot looks exactly as it should. I would like to animate it so that it starts where the data starts (the middle of the curve, intersection of hline and vline) and then follows the time series. When I add transition_reveal, the plot animates from left to right in a wipe like fashion.
p_curve + transition_reveal(along = Var1)
Can anyone help with getting this to reveal along the data series, not the x-axis? Thanks in advance.
I have a data frame(t1) and I want to illustrate the shares of companies in relation to their size
I added a Dummy variable in order to make a filled barplot and not 3:
t1$row <- 1
The size of companies are separated in medium, small and micro:
f_size <- factor(t1$size,
ordered = TRUE,
levels = c("medium", "small", "micro"))
The plot is build up with the economic_theme:
ggplot(t1, aes(x = "Size", y = prop.table(row), fill = f_size)) +
geom_col() +
geom_text(aes(label = as.numeric(f_size)),
position = position_stack(vjust = 0.5)) +
theme_economist(base_size = 14) +
scale_fill_economist() +
theme(legend.position = "right",
legend.title = element_blank()) +
theme(axis.title.y = element_text(margin = margin(r = 20))) +
ylab("Percentage") +
xlab(NULL)
How can I modify my code to get the share for medium, small and micro in the middle of the three filled parts in the barplot?
Thanks in advance!
Your question isn't quite clear to me and I suggest you re-phrase it for clarity. But I believe you're trying to get the annotations to be accurately aligned on the Y-axis. For this use, pre-calculate the labels and then use annotate
library(data.table)
library(ggplot2)
set.seed(3432)
df <- data.table(
cat= sample(LETTERS[1:3], 1000, replace = TRUE)
, x= rpois(1000, lambda = 5)
)
tmp <- df[, .(pct= sum(x) / sum(df[,x])), cat][, cumsum := cumsum(pct)]
ggplot(tmp, aes(x= 'size', y= pct, fill= cat)) + geom_bar(stat='identity') +
annotate('text', y= tmp[,cumsum] - 0.15, x= 1, label= as.character(tmp[,pct]))
But this is a poor decision graphically. Stacked bar charts, by definition sum to 100%. Rather than labeling the components with text, just let the graphic do this for you via the axis labels:
ggplot(tmp, aes(x= cat, y= pct, fill= cat)) + geom_bar(stat='identity') + coord_flip() +
scale_y_continuous(breaks= seq(0,1,.05))
I've been stuck on an issue and can't find a solution. I've tried many suggestions on Stack Overflow and elsewhere about manually ordering a stacked bar chart, since that should be a pretty simple fix, but those suggestions don't work with the huge complicated mess of code I plucked from many places. My only issue is y-axis item ordering.
I'm making a series of stacked bar charts, and ggplot2 changes the ordering of the items on the y-axis depending on which dataframe I am trying to plot. I'm trying to make 39 of these plots and want them to all have the same ordering. I think ggplot2 only wants to plot them in ascending order of their numeric mean or something, but I'd like all of the bar charts to first display the group "Bird Advocates" and then "Cat Advocates." (This is also the order they appear in my data frame, but that ordering is lost at the coord_flip() point in plotting.)
I think that taking the data frame through so many changes is why I can't just add something simple at the end or use the reorder() function. Adding things into aes() also doesn't work, since the stacked bar chart I'm creating seems to depend on those items being exactly a certain way.
Here's one of my data frames where ggplot2 is ordering my y-axis items incorrectly, plotting "Cat Advocates" before "Bird Advocates":
Group,Strongly Opposed,Opposed,Slightly Opposed,Neutral,Slightly Support,Support,Strongly Support
Bird Advocates,0.005473026,0.010946052,0.012509773,0.058639562,0.071149335,0.31118061,0.530101642
Cat Advocates,0.04491726,0.07013396,0.03624901,0.23719464,0.09141056,0.23404255,0.28605201
And here's all the code that takes that and turns it into a plot:
library(ggplot2)
library(reshape2)
library(plotly)
#Importing data from a .csv file
data <- read.csv("data.csv", header=TRUE)
data$s.Strongly.Opposed <- 0-data$Strongly.Opposed-data$Opposed-data$Slightly.Opposed-.5*data$Neutral
data$s.Opposed <- 0-data$Opposed-data$Slightly.Opposed-.5*data$Neutral
data$s.Slightly.Opposed <- 0-data$Slightly.Opposed-.5*data$Neutral
data$s.Neutral <- 0-.5*data$Neutral
data$s.Slightly.Support <- 0+.5*data$Neutral
data$s.Support <- 0+data$Slightly.Support+.5*data$Neutral
data$s.Strongly.Support <- 0+data$Support+data$Slightly.Support+.5*data$Neutral
#to percents
data[,2:15]<-data[,2:15]*100
#melting
mdfr <- melt(data, id=c("Group"))
mdfr<-cbind(mdfr[1:14,],mdfr[15:28,3])
colnames(mdfr)<-c("Group","variable","value","start")
#remove dot in level names
mylevels<-c("Strongly Opposed","Opposed","Slightly Opposed","Neutral","Slightly Support","Support","Strongly Support")
mdfr$variable<-droplevels(mdfr$variable)
levels(mdfr$variable)<-mylevels
pal<-c("#bd7523", "#e9aa61", "#f6d1a7", "#999999", "#c8cbc0", "#65806d", "#334e3b")
ggplot(data=mdfr) +
geom_segment(aes(x = Group, y = start, xend = Group, yend = start+value, colour = variable,
text=paste("Group: ",Group,"<br>Percent: ",value,"%")), size = 5) +
geom_hline(yintercept = 0, color =c("#646464")) +
coord_flip() +
theme(legend.position="top") +
theme(legend.key.width=unit(0.5,"cm")) +
guides(col = guide_legend(ncol = 12)) + #has 7 real columns, using to adjust legend position
scale_color_manual("Response", labels = mylevels, values = pal, guide="legend") +
theme(legend.title = element_blank()) +
theme(axis.title.x = element_blank()) +
theme(axis.title.y = element_blank()) +
theme(axis.ticks = element_blank()) +
theme(axis.text.x = element_blank()) +
theme(legend.key = element_rect(fill = "white")) +
scale_y_continuous(breaks=seq(-100,100,100), limits=c(-100,100)) +
theme(panel.background = element_rect(fill = "#ffffff"),
panel.grid.major = element_line(colour = "#CBCBCB"))
The plot:
I think this works, you may need to play around with the axis limits/breaks:
library(dplyr)
mdfr <- mdfr %>%
mutate(group_n = as.integer(case_when(Group == "Bird Advocates" ~ 2,
Group == "Cat Advocates" ~ 1)))
ggplot(data=mdfr) +
geom_segment(aes(x = group_n, y = start, xend = group_n, yend = start + value, colour = variable,
text=paste("Group: ",Group,"<br>Percent: ",value,"%")), size = 5) +
scale_x_continuous(limits = c(0,3), breaks = c(1, 2), labels = c("Cat", "Bird")) +
geom_hline(yintercept = 0, color =c("#646464")) +
theme(legend.position="top") +
theme(legend.key.width=unit(0.5,"cm")) +
coord_flip() +
guides(col = guide_legend(ncol = 12)) + #has 7 real columns, using to adjust legend position
scale_color_manual("Response", labels = mylevels, values = pal, guide="legend") +
theme(legend.title = element_blank()) +
theme(axis.title.x = element_blank()) +
theme(axis.title.y = element_blank()) +
theme(axis.ticks = element_blank()) +
theme(axis.text.x = element_blank()) +
theme(legend.key = element_rect(fill = "white"))+
scale_y_continuous(breaks=seq(-100,100,100), limits=c(-100,100)) +
theme(panel.background = element_rect(fill = "#ffffff"),
panel.grid.major = element_line(colour = "#CBCBCB"))
produces this plot:
You want to factor the 'Group' variable in the order by which you want the bars to appear.
mdfr$Group <- factor(mdfr$Group, levels = c("Bird Advocates", "Cat Advocates")