I am trying to make the width of all bars in the following plot equal. Can anybody help me? is it possible? or is there any way to plot this data?
library(ggplot2)
dat <- data.frame(x = c('I','I','I','I','II','II'),
y = LETTERS[1:6],
z = abs(rnorm(6)))
ggplot(dat, aes(y,z))+
geom_bar(stat = "identity") +
facet_wrap(~x,scales="free")
I also tried using arguments size and width inside the geom_bar but its not working.
Really the problem is that each of the facet panels is being forced to be the same size and then the plot inside expands to fill all the available room. With facet_grid you can adjust the space for each facet panel (but you cannot seem to do this with facet_wrap). Try
ggplot(dat, aes(y,z))+
geom_bar(stat = "identity") +
facet_grid(~x,scales="free", space="free_x")
which gives me
Related
Hi everyone I want to do a grid bar plot of my data which is the relative abundance of fungi and make it as neat as possible but when I use facet grid the bar plots don't look right to facilitate comparison. Here is the data:
When I use the code :
theme_set(theme_bw())
facet_plot <- ggplot(my_data, aes(x = depth, y = relative abundance, fill = Treatment)) +
geom_bar(stat = "identity", position = "dodge") +
geom_errorbar(aes(ymin=relative abundance-se, ymax=relative abundance+se), width=.2,position=position_dodge(.9))+
facet_grid(. ~ phylum)
I get a plot that looks like this:
As you can see , the plot looks strange especially the last three barplots. Does anyone know how I can modify my code so each plot has its own y axis or any other way of adjusting the scale?
Best wishes
When creating a graphic with ggplot, the size of the panel is adjusted with the other elements, for example the length of the labels in the legend.
We can see an example:
library(ggplot2)
# Create data
data <- data.frame(
name=c("A","B","C","D","E") ,
name2=c("A","B","C","D","E long, very long..... very very long........") ,
value=c(3,12,5,18,45)
)
ggplot(data, aes(x=name, y=value,fill=name)) +
geom_bar(stat = "identity")
ggplot(data, aes(x=name, y=value,fill=name2)) +
geom_bar(stat = "identity")
The problem is that if we create a series of graphics with different variables, the width of the bars is different.
My question is: is it possible to fix the size of the panel, and increase the width of the global ggplot graphic size to display legend?
(PS: one possibility is to create a legend in a separate graphic, but I would also like to explore the options for the overall size the ggplot graphics).
You can control the length of the text using str_wrap
ggplot(data, aes(x=name, y=value,fill=stringr::str_wrap(name2, 10))) +
geom_bar(stat = "identity") +
scale_fill_discrete(name = "Legend")+
theme(legend.margin = margin(r=10,l=5,t=5,b=5))
I am making several instances of a tilted bar chart. As the sizes of count and the differences in percent vary, part of one of the labels (count) is pushed outside the bar in some instances. I need the labels to be entirely inside the bar in all instances. If not repositioned to fit inside the bar, I need the labels to be centered as is.
The code is:
library(tidyverse)
library(ggplot2)
data <- tibble(type = c('Cat', 'Dog'),
group = c('Pets', 'Pets'),
count = c(10000, 990000),
percent = c(1, 99))
ggplot(data, aes(x = group, y = percent, fill = type)) +
geom_bar(stat = 'identity',
position = position_stack(reverse = TRUE)) +
coord_flip() +
geom_text(aes(label = count),
position = position_stack(vjust = 0.5,
reverse = TRUE))
Use hjust="inward":
ggplot(data, aes(x = group, y = percent, fill = type)) +
geom_bar(stat = 'identity', position = position_stack(reverse = TRUE)) +
coord_flip() +
geom_text(aes(label = count), hjust = "inward", position = position_stack(vjust = 0.5, reverse = TRUE))
One thing key to note here is that plots in ggplot are drawn differently depending on the graphics device resolution, width, and height settings. This is why plots look a bit different depending on the computer you use to plot them. If I take your default graph and save different aspect ratios, this becomes evident:
width=3, height=5
width=7, height=5
The aspect ratio and resolution change the plot. You can also see this for yourself within R studio by just resizing the plot viewer window.
With that being said, there are some options to adjust your plot to be less likely to clip text out of bounds:
Rotate your text or rotate your plot back to horizontal bars. For long text labels, they are going to work out better with horizontal bars anyway.
geom_text_repel from the ggrepel package. Direct replacement of geom_text puts your labels in the plot area, and you can use min.segment.length= to specify the minimum line length as well as force= and direction= to play with positioning. Again, works better if you flip back your chart.
Use the expand= argument applied to scale_y_continuous. Try adding scale_y_continuous(expand=c(0.25,0.25)) to your plot, for example. Note that since your coordinate system is flipped, you have to specify "y" to expand "x". This expands the plot area around the geoms.
Change the output width= and height= and resolution when exporting your plots. As indicated above, this is the simple solution.
There are probably other suggestions, but that's mine.
Probably a simple ggplot2 question.
I have a data.frame with a numeric value, a categorical (factor) value, and a character value:
library(dplyr)
set.seed(1)
df <- data.frame(log10.p.value=c(-2.5,-2.5,-2.5,-2.39,-2,-1.85,-1.6,-1.3,-1.3,-1),
direction=sample(c("up","down"),10,replace = T),
label=paste0("label",1:10),stringsAsFactors = F) %>% dplyr::arrange(log10.p.value)
df$direction <- factor(df$direction,levels=c("up","down"))
I want to plot these data as a barplot using geom_bar, where the bars are horizontal and their lengths are determined by df$log10.p.value, their color by df$direction, and the y-axis tick labels are df$label, where the bars are vertically ordered by df$log10.p.value.
As you can see df$log10.p.value are not unique, hence:
ggplot(df,aes(log10.p.value))+geom_bar(aes(fill=direction))+theme_minimal()+coord_flip()+ylab("log10(p-value)")+xlab("")
Gives me:
How do I:
Make the bars not overlap each other.
Have the same width.
Be separated by a small margin?
Have the y-axis tick labels be df$label?
Thanks
Here is one possible solution. Please note that, by default, geom_bar determines the bar length using frequency/count. So, you need to specify stat = "identity" for value mapping.
# since all of your values are negative the graph is on the left side
ggplot(df, aes(x = label, y = log10.p.value, fill = direction)) +
geom_bar(stat = "identity") +
theme_minimal() +
coord_flip() +
ylab("log10(p-value)") +
xlab("")
I have a dataset where measurements are made for different groups at different days.
I want to have side by side bars representing the measurements at the different days for the different groups with the groups of bars spaced according to day of measurement with errorbars overlaid to them.
I'm having trouble with making the dodging in geom_bar agree with the dodge on geom_errorbar.
Here is a simple piece of code:
days = data.frame(day=c(0,1,8,15));
groups = data.frame(group=c("A","B","C","D", "E"), means=seq(0,1,length=5));
my_data = merge(days, groups);
my_data$mid = exp(my_data$means+rnorm(nrow(my_data), sd=0.25));
my_data$sigma = 0.1;
png(file="bar_and_errors_example.png", height=900, width=1200);
plot(ggplot(my_data, aes(x=day, weight=mid, ymin=mid-sigma, ymax=mid+sigma, fill=group)) +
geom_bar (position=position_dodge(width=0.5)) +
geom_errorbar (position=position_dodge(width=0.5), colour="black") +
geom_point (position=position_dodge(width=0.5), aes(y=mid, colour=group)));
dev.off();
In the plot, the errorsegments appears with a fixed offset from its bar (sorry, no plots allowed for newbies even if ggplot2 is the subject).
When binwidth is adjusted in geom_bar, the offset is not fixed and changes from day to day.
Notice, that geom_errorbar and geom_point dodge in tandem.
How do I get geom_bar to agree with the other two?
Any help appreciated.
The alignment problems are due, in part, to your bars not representing the data you intend. The following lines up correctly:
ggplot(my_data, aes(x=day, weight=mid, ymin=mid-sigma, ymax=mid+sigma, fill=group)) +
geom_bar (position=position_dodge(), aes(y=mid), stat="identity") +
geom_errorbar (position=position_dodge(width=0.9), colour="black") +
geom_point (position=position_dodge(width=0.9), aes(y=mid, colour=group))
This is an old question, but since i ran into the problem today, i want to add the following:
In
geom_bar(position = position_dodge(width=0.9), stat = "identity") +
geom_errorbar( position = position_dodge(width=0.9), colour="black")
the width-argument within position_dodge controls the dodging width of the things to dodge from each other. However, this produces whiskers as wide as the bars, which is possibly undesired.
An additional width-argument outside the position_dodge controls the width of the whiskers (and bars):
geom_bar(position = position_dodge(width=0.9), stat = "identity", width=0.7) +
geom_errorbar( position = position_dodge(width=0.9), colour="black", width=0.3)
The first change I reformatted the code according to the advanced R style guide.
days <- data.frame(day=c(0,1,8,15))
groups <- data.frame(
group=c("A","B","C","D", "E"),
means=seq(0,1,length=5)
)
my_data <- merge(days, groups)
my_data$mid <- exp(my_data$means+rnorm(nrow(my_data), sd=0.25))
my_data$sigma <- 0.1
Now when we look at the data we see that day is a factor and everything else is the same.
str(my_data)
To remove blank space from the plot I converted the day column to factors. CHECK that the levels are in the proper order before proceeding.
my_data$day <- as.factor(my_data$day)
levels(my_data$day)
The next change I made was defining y in your aes arguments. As I'm sure you are aware, this lets ggplot know where to look for y values. Then I changed the position argument to "dodge" and added the stat="identity" argument. The "identity" argument tells ggplot to plot y at x. geom_errorbar inherits the dodge position from geom_bar so you can leave it unspecified, but geom_point does not so you must specify that value. The default dodge is position_dodge(.9).
ggplot(data = my_data,
aes(x=day,
y= mid,
ymin=mid-sigma,
ymax=mid+sigma,
fill=group)) +
geom_bar(position="dodge", stat = "identity") +
geom_errorbar( position = position_dodge(), colour="black") +
geom_point(position=position_dodge(.9), aes(y=mid, colour=group))
sometimes you put aes(x=tasks,y=val,fill=group) in geom_bar rather than ggplot. This causes the problem since ggplot looks forward x and you specify it by the location of each group.