Below is my code to plot Stacked BarPlot
ggplot(data = mdata, aes(x = variable, y = value, fill = Species)) +
geom_bar(position = "fill", stat = "identity") +
theme(legend.text=element_text(size=rel(0.7)),
legend.key.size = unit(0.5, "cm")) +
scale_y_continuous(labels=function(x)x*100) +
coord_flip() +
ylab("Species Percentage") +
xlab("Samples")
OutputPlot:
As you can see from the plot my Species legends are split in to 5 column list, which takes the 50% of the total plot layout.
Is there a way to make/convert legend list in to only 2 or 3 column so that area above and below will be covered and BarPlot can be widened.
Also to make Legend Text Bold its looking blurred with many legends
You can set any number of columns with the ncol argument in guide_legend():
library(ggplot2)
dat <- cbind(car = rownames(mtcars), mtcars)
ggplot(dat, aes(mpg, wt, colour = car)) +
geom_point() +
scale_colour_discrete(guide = guide_legend(ncol = 3))
EDIT: As Z.Lin pointed out, for fill scales; replace scale_colour_* by scale_fill_*.
Related
it want to make a plot of this type in ggplot, but cant get it to work (made in excel):
So that there are cities on the x-axis, but they are arranged according to which state they are in.
The color of each bar is based on some third property, for example size of city (large, small or medium), and the y-axis is a measurement of whatever! A legend of (large, small, medium) should be included, just isn't in the figure I pasted here.
Example data:
state <- c(rep("Texas",3),rep("Colorado",3),rep("Nevada",3))
city <- c("Houston","Austin","Dallas","Denver","Boulder","Aspen","Reno","Sparks","Henderson")
size <- c(rep(c("large","medium","small"),3))
value <- runif(9, 10,50)
df <- data.frame(state,city,size, value)
So far, I have done this:
plot <- ggplot(df, aes(x=State, y=value)) +
geom_bar(aes(fill=size),position = "dodge", stat = "identity", color="black")
plot
But then each bar is not labeled with the city name.
Any ideas?
Answer
(Credit to https://dmitrijskass.netlify.app/2019/06/30/multi-level-labels-with-ggplot2/ )
Use facet_grid:
ggplot(df, aes(x=city, y = value)) +
geom_col() +
facet_grid(~ state,
scales = "free_x",
space = "free_x",
switch = "x")
More complete version
ggplot(df, aes(x=city, y = value)) +
geom_col() +
facet_grid(~ state,
scales = "free_x",
space = "free_x",
switch = "x") +
theme(panel.spacing = unit(0, units = "cm"), # removes space between panels
strip.placement = "outside", # moves the states down
strip.background = element_rect(fill = "white") # removes the background from the state names
I want to somehow indicate that certain rows in a multipanel figure should be compared together. For example, I want to make this plot:
Look like this plot (with boxes around panels made with PowerPoint):
Here's the code I made to use the first plot. I used ggplot and cowplot:
require(cowplot)
theme_set(theme_cowplot(font_size=12)) # reduce default font size
plot.mpg <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
plot.diamonds <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
plot.mpg2 <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
plot.diamonds2 <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
plot_grid(plot.mpg, plot.diamonds,plot.mpg2, plot.diamonds2, nrow=2,labels = c('A', 'B','C','D'))
Is there a change I can make to this code to get the borders that I want? Or maybe can I even make the panels A and B have a slightly different color than the background for panels C and D? That might be even better.
Since the result of plot_grid() is a ggplot object, one way to do this is to use nested plot grids: one plot_grid() for each row, with the appropriate border added via theme().
plot_grid(
# row 1
plot_grid(plot.mpg, plot.diamonds, nrow = 1, labels = c('A', 'B')) +
theme(plot.background = element_rect(color = "black")),
# row 2
plot_grid(plot.mpg2, plot.diamonds2, nrow = 1, labels = c('C', 'D')) +
theme(plot.background = element_rect(color = "black")),
nrow = 2)
I'd like to add a line below the x-axis where its color is dependant on a factor that is not plotted.
In this example, I'm creating a box plot and would like to add a line that indicates another variable.
Using the cars data set as an example and then physically dawing in what I'm trying to do:
ggplot(mtcars, aes(factor(cyl), mpg, fill=factor(am))) +
geom_boxplot()
My thought was to create a bar, column, or geom_tile plot and then arrange it below the boxplot. This is how I would do it in base R. Is there a way to add in these kinds of color labels in ggplot2?
The natural way in ggplot2 to do this sort of thing would to be facet on the categorical variable to create subplots. However if you want to keep everything on the same graph you could try using a geom_tile() layer something like this:
df <-data.frame(x = factor(c(4,6,8)), colour = factor(c(1,2,1)))
ggplot(mtcars, aes(factor(cyl), mpg, fill=factor(am))) +
geom_boxplot() +
geom_tile(data=df, aes(x = x, y = 8, fill = colour))
Alternatively as you suggest you could align an additional plot underneath it. You could use ggarrange() in the ggpubr package for this:
plot1 <- ggplot(mtcars, aes(factor(cyl), mpg, fill=factor(am))) +
geom_boxplot() +
geom_tile(data=df, aes(x = x, y = 10, fill = colour))
theme(legend.position = 'none')
plot2 <- ggplot(df, aes(x=x, y=1, fill = colour)) +
geom_tile() +
theme_void() +
scale_fill_manual(values=c('orange', 'green', 'orange')) +
theme(legend.position = 'none')
library(ggpubr)
ggarrange(plot1, plot2, nrow = 2, heights = c(10, 1), align = 'h')
I have a dataframe of multiple columns (let's say n) with different range and a vector of length n. I want different x-axis for each variable to be shown below each box plot. I tried facet_grid and facet_wrap but it gives common x axis.
This is what I have tried:
d <- data.frame(matrix(rnorm(10000), ncol = 20))
point_var <- rnorm(20)
plot.data <- gather(d, variable, value)
plot.data$test_data <- rep(point_var, each = nrow(d))
ggplot(plot.data, aes(x=variable, y=value)) +
geom_boxplot() +
geom_point(aes(x=factor(variable), y = test_data), color = "red") +
coord_flip() +
xlab("Variables") +
theme(legend.position="none")
If you can live with having the text of the x axis above the plot, and having the order of the graphs a bit messed-up this could work:
library(grid)
p = ggplot(plot.data, aes(x = 0, y=value)) +
geom_boxplot() +
geom_point(aes(x = 0, y = test_data), color = "red") +
facet_wrap(~variable, scales = "free_y", switch = "y") +
xlab("Variables") +
theme(legend.position="none") + theme_bw() + theme(axis.text.x=element_blank())
print(p, vp=viewport(angle=270, width = unit(.75, "npc"), height = unit(.75, "npc")))
I'm actually just creating the graph without flipping coords, so that scales = 'free_y' works, swithcing the position of the strip labels, and then rotating the graph.
If you don't like the text above graph (which is understandable), I would consider creating a list of single plots and then putting them together with grid.arrange.
HTH,
Lorenzo
I'll use violin plots here as an example, but the question extends to many other ggplot types.
I know how to subset my data along the x-axis by a factor:
ggplot(iris, aes(x = Species, y = Sepal.Length)) +
geom_violin() +
geom_point(position = "jitter")
And I know how to plot only the full dataset:
ggplot(iris, aes(x = 1, y = Sepal.Length)) +
geom_violin() +
geom_point(position = "jitter")
My question is: is there a way to plot the full data AND a subset-by-factor side-by-side in the same plot? In other words, for the iris data, could I make a violin plot that has both "full data" and "setosa" along the x-axis?
This would enable a comparison of the distribution of a full dataset and a subset of that dataset. If this isn't possible, any recommendations on better way to visualise this would also be welcome :)
Thanks for any ideas!
Using:
ggplot(iris, aes(x = "All", y = Sepal.Length)) +
geom_violin() +
geom_point(aes(color="All"), position = "jitter") +
geom_violin(data=iris, aes(x = Species, y = Sepal.Length)) +
geom_point(data=iris, aes(x = Species, y = Sepal.Length, color = Species),
position = "jitter") +
scale_color_manual(values = c("black","#F8766D","#00BA38","#619CFF")) +
theme_minimal(base_size = 16) +
theme(axis.title.x = element_blank(), legend.title = element_blank())
gives: