How do I show legend for the following ggplot bar plot?
tmp <- data.frame(group = LETTERS[1:10], id = 10:1, a = runif(10), b = runif(10))
ggplot(tmp) + geom_bar(aes(x = reorder(group, id), a + b, group = 1), stat = 'identity')
Update: I have two charts arranged using grid.arrange from gridExtra. Both charts have the same number of bars, but one has legend. I thought that by adding any legend to the second chart, I will align the bars (make width of plot area of both plots the same):
tmp <- data.frame(group = LETTERS[1:10], id = 10:1,
a = runif(10), b = runif(10), c = rnorm(10))
p1 <- ggplot(tmp) + geom_bar(aes(x = reorder(group, id), c, fill = a), stat = 'identity')
p2 <- ggplot(tmp) + geom_bar(aes(x = reorder(group, id), a + b, group = 1), stat = 'identity')
library(gridExtra)
grid.arrange(p1, p2, heights = c(2, 1) )
Now, it looks like this:
You can try something like this for p2, which will create a new legend for the bottom graph.
p2 <- ggplot(tmp) + geom_bar(aes(x = reorder(group, id), a + b, group = 1, fill = 0), stat = 'identity') +
guides(fill=guide_legend(title="Title"))
This is what i needed
guides(fill=guide_legend(title="Title"))
Thanks
Related
I have made the graph below with ggplot. I would like to reduce the distance between the y axis and the first category (a). Which function should I use? Thanks! :)
library(ggplot2)
library(reshape2)
data <- data.frame(a = rnorm(10), b = rnorm(10), c = rnorm(10), group = 1:10)
data <- melt(data, id = "group")
ggplot(data, aes(x = variable, y = value, group = group, color = as.factor(group))) + geom_point() + geom_line() + theme_minimal() + theme(axis.line = element_line(), panel.grid = element_blank())
Suppose we have the following plot:
library(ggplot2)
df <- data.frame(x = rep(LETTERS[1:3], 3),
y = rnorm(9),
z = rep(letters[1:3], each = 3))
ggplot(df, aes(x, y, colour = z, group = z)) +
geom_line() +
geom_point()
We can reduce the space between the extreme points and the panel edges by adjusting the expand argument in a scale function:
ggplot(df, aes(x, y, colour = z, group = z)) +
geom_line() +
geom_point() +
scale_x_discrete(expand = c(0,0.1))
Setting expand = c(0,0) completely removes the space. The first argument is a relative number, the second an absolute; so in the example above we set the expand to 0.1 x-axis units.
I am trying to create a plot that will be combination of 6 plots made in ggplot2. The conditions are
One main title
Three subtitles
Common background color
Diffrent sizes of plots
One legend at the bottom
And it should look something like it:
I have found bits and pices, but I dont know how to put it togheter.
To add main title I used Place title of multiplot panel with ggplot2
layout <- matrix(c(1, 1, 2, 3, 3, 4), nrow = 2, byrow = TRUE)
grid.arrange(A, B, C, D, top = "Title",
layout_matrix = layout)
I have found function multiplot (http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2)/) and it dose allow to plot several charts with diffrent sizes, but the other reqirements are not met
plot_list <- list(A, B, C, D)
layout <- matrix(c(1, 1, 2, 3, 3, 4), nrow = 2, byrow = TRUE)
multiplot(plotlist = plot_list, layout = layout)
I have also found how to create common legend, but the charts sizes are the same (Add a common Legend for combined ggplots)
grid_arrange_shared_legend <- function(...) {
plots <- list(...)
g <- ggplotGrob(plots[[1]] + theme(legend.position="bottom"))$grobs
legend <- g[[which(sapply(g, function(x) x$name) == "guide-box")]]
lheight <- sum(legend$height)
grid.arrange(
do.call(arrangeGrob, lapply(plots, function(x)
x + theme(legend.position="none"))),
legend,
ncol = 1,
heights = unit.c(unit(1, "npc") - lheight, lheight))
}
grid_arrange_shared_legend(A, B, C, D)
sample data
DF <- data.frame(ID = 1:10, Pop = (1:10)^2, gr = c("A", rep("B", 8), "A"))
DF_Pie <- DF %>%
group_by(gr) %>%
summarise(Years = n(),
Pop_Years = sum(Pop))
A <- ggplot(DF, aes(x = ID, col = gr, fill = gr)) +
geom_bar()+
theme(legend.position="none")
B <- ggplot(DF_Pie, aes(x = factor(1), y = Years, fill = gr))+
geom_bar(width = 1, stat = "identity") +
coord_polar("y", start=0)+
theme(legend.position="none")
C <- ggplot(DF, aes(x = ID, y = Pop, col = gr, fill = gr)) +
geom_bar(stat="identity") +
theme(legend.position="bottom")
D <- ggplot(DF_Pie, aes(x = factor(1), y = Pop_Years, fill = gr))+
geom_bar(width = 1, stat = "identity") +
coord_polar("y", start=0) +
theme(legend.position="none")
EDIT
Thanks to #hpesoj626 I know how to make everything, but the condition 3 still applys - the common background color
EDIT 2
I have created following chart but the space between plots and titles are huge
From the linked post, there is a ggpubr solution. I looked at the package and saw ggpubr::anotate_figure, which seems able to do what you want. I did some tweaks with the plots A, B, C, D.
A <- ggplot(DF, aes(x = ID, col = gr, fill = gr)) +
geom_bar() +
xlab(NULL) + theme(legend.position = "none")
B <- ggplot(DF_Pie, aes(x = factor(1), y = Years, fill = gr))+
geom_bar(width = 1, stat = "identity") +
coord_polar("y", start=0) + labs(x = NULL, y = NULL) + theme(legend.position = "none")
C <- ggplot(DF, aes(x = ID, y = Pop, col = gr, fill = gr)) +
geom_bar(stat="identity")
D <- ggplot(DF_Pie, aes(x = factor(1), y = Pop_Years, fill = gr))+
geom_bar(width = 1, stat = "identity") +
coord_polar("y", start=0) + labs(x = NULL, y = NULL)
p1 <- ggarrange(A, B, ncol=2)
p2 <- ggarrange(C, D, ncol=2, common.legend = TRUE, legend = "bottom")
p1 <- annotate_figure(p1, top = text_grob("According to years"))
p2 <- annotate_figure(p2, top = text_grob("According to population"))
p <- ggarrange(p1, p2, nrow=2, common.legend = TRUE, legend="bottom", heights = c(3,3.75))
annotate_figure(p, top = text_grob("Main title", face = "bold", size = 16))
As the code below, I constructed a plotly from a ggplot, and want to change the position of the legend.
df <- data.frame(n=1:10, Var1 = rnorm(10), Var2 = rnorm(10))
data_long <- melt(df, id = "n")
a <- ggplot(data_long,
aes(x = n, y = value, colour = variable, group = variable)) +
geom_line()
ggplotly(a) %>% layout(legend = list(x = 0, y = 0), yaxis = list(title = ""))
The ggplot looks like
But the plotly looks like
Part of the legend title is still on the top of the graph.
You can use legend.position argument:
a <- ggplot(data_long,
aes(x = n, y = value, colour = variable, group = variable)) +
geom_line() +
theme(legend.justification=c(0,0), legend.position=c(0,0))
I'm trying to build a stacked bar chart from a 2x2 dataframe. I'm using ggplot2 1.0.0. Unfortunately, the column with data for the B level only shows one colour, instead of two.
df <- data.frame(x1 = rep(c("A","B"), each = 2), x2 = c(75.0, 25.0, 50.0, 50.0))
fig1 <- ggplot(data = df, aes(x = x1, y = x2)) + geom_bar(aes(x1, fill = x2), stat = "identity") + xlab("") + ylab("%") + ggtitle("df")
fig1 + geom_text(aes(label = x2), vjust = -0.8, colour = "white")
The code produces the following graph: http://imgur.com/j3DEO5h
Any ideas?
You used a continous scale for fill, so two 50 values have the same colour. You could use a discrete scale like this:
ggplot(transform(df, var = as.factor(1:2)),
aes(x = x1, y = x2, fill = var)) +
geom_bar(stat = "identity")
I'm trying to annotate a bar chart with the percentage of observations falling into that bucket, within a facet. This question is very closely related to this question:
Show % instead of counts in charts of categorical variables but the introduction of faceting introduces a wrinkle. The answer to the related question is to use stat_bin w/ the text geom and then have the label be constructed as so:
stat_bin(geom="text", aes(x = bins,
y = ..count..,
label = paste(round(100*(..count../sum(..count..)),1), "%", sep="")
)
This works fine for an un-faceted plot. However, with facets, this sum(..count..) is summing over the entire collection of observations without regard for the facets. The plot below illustrates the issue---note that the percentages do not sum to 100% within a panel.
Here the actually code for the figure above:
g.invite.distro <- ggplot(data = df.exp) +
geom_bar(aes(x = invite_bins)) +
facet_wrap(~cat1, ncol=3) +
stat_bin(geom="text", aes(x = invite_bins,
y = ..count..,
label = paste(round(100*(..count../sum(..count..)),1), "%", sep="")
),
vjust = -1, size = 3) +
theme_bw() +
scale_y_continuous(limits = c(0, 3000))
UPDATE: As per request, here's a small example re-producing the issue:
df <- data.frame(x = c('a', 'a', 'b','b'), f = c('c', 'd','d','d'))
ggplot(data = df) + geom_bar(aes(x = x)) +
stat_bin(geom = "text", aes(
x = x,
y = ..count.., label = ..count../sum(..count..)), vjust = -1) +
facet_wrap(~f)
Update geom_bar requires stat = identity.
Sometimes it's easier to obtain summaries outside the call to ggplot.
df <- data.frame(x = c('a', 'a', 'b','b'), f = c('c', 'd','d','d'))
# Load packages
library(ggplot2)
library(plyr)
# Obtain summary. 'Freq' is the count, 'pct' is the percent within each 'f'
m = ddply(data.frame(table(df)), .(f), mutate, pct = round(Freq/sum(Freq) * 100, 1))
# Plot the data using the summary data frame
ggplot(data = m, aes(x = x, y = Freq)) +
geom_bar(stat = "identity", width = .7) +
geom_text(aes(label = paste(m$pct, "%", sep = "")), vjust = -1, size = 3) +
facet_wrap(~ f, ncol = 2) + theme_bw() +
scale_y_continuous(limits = c(0, 1.2*max(m$Freq)))