I want to add a legend for the plot, but it doesn't work,
can anyone please help me to see where it went wrong.
this is the code.
ggplot(data = dfNorm1, aes(x = X)) +
geom_col(aes(y = Government_suppliment),
fill = "#0000FF", color = "white", alpha = 0.8) +
geom_smooth(data = subset(dfNorm1,X >= 24), aes(y = Government_suppliment),
method = "lm", se = FALSE, color = "#FF4040",
linetype = "dashed", size = 0.7) +
geom_smooth(data = subset(dfNorm1, X <= 24), aes(y = Government_suppliment),
method = "lm", se = FALSE, color = "#FF4040",
linetype = "dashed", size = 0.7) +
geom_vline(xintercept = 24.5, size = 0.8, alpha = 0.8) +
geom_line(aes(y = Poverty_funds),
color = "#FF0000", size = 1, alpha = 0.7) +
geom_line(aes(y = MLI), color = "#EF3EFF", size = 1,
alpha = 0.8) +
scale_fill_manual(name = "",values = c("bar.label" = "#0000FF")) +
scale_color_manual(name = "", values = c("line.label1" = "#FF0000", "line.label2" = "#EF3EFF",
"line.labeld" = "#FF4040"))
You usually can produce a legend by setting aes(color = column_title) in one of your geom layers. This code doesn't particularly make sense because you are referencing more than one y-axis without creating a second y-axis (a bad habit if you are trying to do so). Is there a way you can post more relevant code or a reproducible example so people can see exactly what you're trying to do?
Related
I am trying to add labels to a ggplot object. The labels do not look neat and tidy due to their positioning. I have tried using various geom_label_repel and geom_text_repel options but am not having much luck.
I cannot share the data unfortunately, but I have inserted one of my codes below and a screenshot of one section of the redacted graph. The graph has multiple peaks that need labelling. Each label has 2 lines.
I would like the lines connecting the labels to be directly above each peak on the x axis, then turn at a right angle and the line continue horizontally slightly. I would then like the label to sit on top of this horizontal section of the line.
Some peaks are very close together, so the labels will end up being pushed up the y axis so they are able to stack up neatly.
I hope that description makes sense. I would appreciate it if anyone is able to help.
Thank you!
library(ggplot2)
library(ggrepel)
library(dplyr)
upper_plot <- ggplot() +
geom_point(data = plot_data[which(analysis == "Analysis1"),],
aes(x = rel_pos, y = logged_p, color = as.factor(chr)),
size = 0.25) +
scale_color_manual(values = rep(my_upper_colors, nrow(axis_df))) +
geom_point(data=upper_highlight_pos2_old,
aes(x = rel_pos, y = logged_p),
color= c('grey'),
size=0.75,
pch = 16) +
geom_point(data=upper_labels_old,
aes(x = rel_pos, y = logged_p),
color='dark grey',
size=2,
pch = 18) +
geom_point(data=upper_highlight_pos2_novel,
aes(x = rel_pos, y = logged_p),
color= c('black'),
size=0.75,
pch = 16) +
geom_point(data=upper_labels_novel,
aes(x = rel_pos, y = logged_p),
color='black',
size=2,
pch = 18) +
scale_x_continuous(labels = axis_df$chr,
breaks = axis_df$chr_center,
expand = expansion(mult = 0.01)) +
scale_y_continuous(limits = c(0, maxp),
expand = expansion(mult = c(0.02, 0.06))) +
# geom_hline(yintercept = -log10(1e-5), color = "red", linetype = "dashed",
# size = 0.3) +
geom_hline(yintercept = -log10(5e-8), color = "black", linetype = "dashed",
size = 0.3) +
labs(x = "", y = bquote(atop('GWAS', '-log'[10]*'(p)'))) +
theme_classic() +
theme(legend.position = "none",
axis.title.x = element_blank(),
plot.margin = margin(t=5, b = 5, r=5, l = 10)) +
geom_label_repel(data = upper_labels,
aes(x = rel_pos, y = logged_p, label = label),
ylim = c(maxp / 3, NA),
size = 2,
force_pull = 0,
nudge_x = 0.5,
box.padding = 0.5,
nudge_y = 0.5,
min.segment.length = 0, # draw all lines no matter how short
segment.size = 0.2,
segment.curvature = -0.1,
segment.ncp = 3,
segment.angle = 45,
label.size=NA, #no border/box
fill = NA, #no background
)
This is my current untidy layout...
EDIT:
This is the sort of layout I am after. The lines will need to be flexible and either be right-handed or left-handed depending on space (source: https://www.nature.com/articles/s41588-020-00725-7)
Suppose I have data with both an ordinal variable and a categorical variable:
set.seed(35)
df <- data.frame(Class = factor(rep(c(1,2),times = 80), labels = c("Math","Science")),
StudyTime = factor(sort(sample(1:4, 16, prob = c(0.25,0.3,0.3,0.15), replace = TRUE)),labels = c("<5","5-10","10-20",">20")),
Nerd = factor(sapply(rep(c(0.1,0.3,0.5,0.8),c(30,50,50,30)), function(x)sample(c("Nerd","NotNerd"),size = 1, prob = c(x,1-x))),levels = c("NotNerd","Nerd")))
One could use ggplot and geom_bar with x, fill and alpha (or color) aesthetic mappings to visualize the relationship between these variables.
ggplot(data = df, aes(x = Class, fill = StudyTime, alpha = Nerd)) +
geom_bar(position = "dodge", color = "black") +
scale_alpha_manual(values = c(Nerd = 0.5, NotNerd = 1)) +
scale_fill_manual(values = colorRampPalette(c("#0066CC","#FFFFFF","#FF8C00"))(4)) +
labs(x = "Class", y = "Number of Students", alpha = "Nerd?") +
theme(legend.key.height = unit(1, "cm"))
However, alpha and color are not ideal. A better alternative might be to apply a pattern such as stripes or a crosshatch.
The accepted answer to this question from over 10 years ago says to use colors, and the most upvoted answer (while clever) uses over 100 lines of code.
This question received some upvotes but no new answers.
Is there any better alternative to adding a pattern such as can be seen here?
One approach is to use the ggpattern package written by Mike FC (no affiliation):
library(ggplot2)
#remotes::install_github("coolbutuseless/ggpattern")
library(ggpattern)
ggplot(data = df, aes(x = Class, fill = StudyTime, pattern = Nerd)) +
geom_bar_pattern(position = position_dodge(preserve = "single"),
color = "black",
pattern_fill = "black",
pattern_angle = 45,
pattern_density = 0.1,
pattern_spacing = 0.025,
pattern_key_scale_factor = 0.6) +
scale_fill_manual(values = colorRampPalette(c("#0066CC","#FFFFFF","#FF8C00"))(4)) +
scale_pattern_manual(values = c(Nerd = "stripe", NotNerd = "none")) +
labs(x = "Class", y = "Number of Students", pattern = "Nerd?") +
guides(pattern = guide_legend(override.aes = list(fill = "white")),
fill = guide_legend(override.aes = list(pattern = "none")))
The package appears to support a number of common geometries. Here is an example of using geom_tile to combine a continuous variable with a categorical variable:
set.seed(40)
df2 <- data.frame(Row = rep(1:9,times=9), Column = rep(1:9,each=9),
Evaporation = runif(81,50,100),
TreeCover = sample(c("Yes", "No"), 81, prob = c(0.3,0.7), replace = TRUE))
ggplot(data=df2, aes(x=as.factor(Row), y=as.factor(Column),
pattern = TreeCover, fill= Evaporation)) +
geom_tile_pattern(pattern_color = NA,
pattern_fill = "black",
pattern_angle = 45,
pattern_density = 0.5,
pattern_spacing = 0.025,
pattern_key_scale_factor = 1) +
scale_pattern_manual(values = c(Yes = "circle", No = "none")) +
scale_fill_gradient(low="#0066CC", high="#FF8C00") +
coord_equal() +
labs(x = "Row",y = "Column") +
guides(pattern = guide_legend(override.aes = list(fill = "white")))
I am quite new to ggplot2 and it's been challenging to reproduce a similar chart in Excel. I almost got it to work, but now I need to figure out a way to make the geom_point/line's legend key (3rd item in the legend) to not show the box around it.
Note: I know there are answers to similar problem by using + theme(legend.key = element_blank()), but it has no effect on the legend. I suspect it has something to do with the scale_*_manual in the code. Any other solutions would be truly appreciated!
test <- data.frame(
group = 1:5,
cnt = rep(600, 5),
pct_cnt = rep(0.2, 5),
prem = c(12000000, 9800000, 8700000, 11000000, 3500000),
pct_prem = c(0.266666667, 0.217777778, 0.193333333, 0.244444444,
0.077777778),
relativity = c(1.5, 1.2, 1, 0.8, 0.4)
)
theme_set(theme_minimal())
normalizer <- round(max(test$relativity) / max(test$pct_prem), 0)
ggplot(test, aes(x = group)) +
geom_bar(aes(y = pct_prem, fill = 'prem', color = 'prem'), stat = 'identity', position = position_nudge(x = -0.1), width = 0.2) +
geom_bar(aes(y = pct_cnt, fill = 'cnt', color = 'cnt'), stat = 'identity', position = position_nudge(x = 0.1), width = 0.2) +
geom_point(aes(y = relativity / normalizer, color = 'rel', fill = 'rel'), size = 5) +
geom_line(aes(y = relativity / normalizer, color = 'rel'), size = 2) +
scale_color_manual(name = 'metric', values = c('prem' = NA, 'cnt' = NA, 'rel' = 'skyblue'),
labels = c('prem' = '%Prem', 'cnt' = '%Count', 'rel' = 'LRR')) +
scale_fill_manual(name = 'metric', values = c('prem' = 'orange', 'cnt' = 'dark green', 'rel' = NA),
labels = c('prem' = '%Prem', 'cnt' = '%Count', 'rel' = 'LRR')) +
scale_y_continuous(limits = c(0, 0.4), sec.axis = sec_axis(~.*normalizer, breaks = seq(0, 0.4, 0.1) * normalizer, name = 'relativity'))
I'm not sure if there is a method using just ggplot, since the color of the box and the color of your legend key itself change simultaneously when using the common override.aes fix. Going into the gtable, you could do it this way (after assigning your plot to p):
library(grid)
grb <- ggplotGrob(p)
#get the index of the legend-grob and store grob as leg
leg_index <- grep("guide-box", sapply(grb$grobs, function(x) x$name))
leg <- grb$grobs[[leg_index]]
Then, you want to look in the legend's gtable. The key bg to be changed is the last one, so check at the bottom for rect backgrounds. I.e., here
13 13 (6-6,2-2) key-5-1-bg zeroGrob[legend.key..zeroGrob.3081]
14 14 (6-6,2-2) key-5-1-1 rect[GRID.rect.3082]
15 15 (6-6,2-2) key-5-1-2 rect[GRID.rect.3083]
16 16 (6-6,2-2) key-5-1-3 points[GRID.points.3084]
17 17 (6-6,2-2) key-5-1-4 segments[GRID.segments.3085]
Indices 14 and 15 are the ones belonging to the last key. To make sure the bg is removed, just change the graphic parameters of both of them. Then replace the old legend with your changed one.
leg$grobs[[1]]$grobs[[14]]$gp$col <- "white"
leg$grobs[[1]]$grobs[[15]]$gp$col <- "white"
grb$grobs[[leg_index]] <- leg
grid.newpage()
grid.draw(grb)
To move a legend on the bottom of the graph you add "bottom" to legend.position like this....
theme(legend.position="bottom")
here is your original code adjusted..
ggplot(test, aes(x = group)) +
geom_bar(aes(y = pct_prem, fill = 'prem', color = 'prem'), stat = 'identity', position = position_nudge(x = -0.1), width = 0.2, alpha = 1) +
geom_bar(aes(y = pct_cnt, fill = 'cnt', color = 'cnt'), stat = 'identity', position = position_nudge(x = 0.1), width = 0.2) +
geom_point(aes(y = relativity / normalizer, color = 'rel', fill = 'rel'), size = 5) +
geom_line(aes(y = relativity / normalizer, color = 'rel'), size = 2) +
scale_color_manual(name = 'metric', values = c('prem' = NA, 'cnt' = NA, 'rel' = 'skyblue'),
labels = c('prem' = '%Prem', 'cnt' = '%Count', 'rel' = 'LRR')) +
scale_fill_manual(name = 'metric', values = c('prem' = 'orange', 'cnt' = 'dark green', 'rel' = NA),
labels = c('prem' = '%Prem', 'cnt' = '%Count', 'rel' = 'LRR')) +
scale_y_continuous(limits = c(0, 0.4) , sec.axis = sec_axis(~.*normalizer, breaks = seq(0, 0.4, 0.1) * normalizer, name = 'relativity'))+
theme(legend.position="bottom")
For further adjustments that can be made look up theme (tons of options)
?theme
Hope this helps!
I'm new to R and I tried to solve the problem looking for other questions, but I coulndn't. I have a problem with overlapping different heatmaps I created using ggplot2 and ggmap. When plotting the maps singularly it works. Only when I try to plot them together the error :
Scale for 'fill' is already present. Adding another scale for 'fill', which will replace the existing scale.
appears.
This is my code:
us_map_g_str <- get_map(location = "detroit", zoom = 10)
ggmap(us_map_g_str, extent = "device") +
geom_density2d(data = data1,
aes(x=as.numeric(lon), y = as.numeric(lat)),
size = 0.3) +
stat_density2d(data = data1,
aes(x = as.numeric(lon), y = as.numeric(lat),
fill = ..level.., alpha = ..level..),
size = 0.3, bins = 500, geom = "polygon") +
scale_fill_gradient(low = "green", high = "red") +
scale_alpha(range = c(0, 0.3), guide = FALSE) +
geom_density2d(data = data2,
aes(x = as.numeric(lon), y = as.numeric(lat)),
size = 0.3) +
stat_density2d(data = data2,
aes(x = as.numeric(lon), y = as.numeric(lat),
fill = ..level.., alpha = ..level..),
size = 0.3, bins = 500, geom = "polygon") +
scale_fill_gradient(low = "blue", high = "black") +
scale_alpha(range = c(0, 0.3), guide = FALSE) +
geom_density2d(data = data3,
aes(x = as.numeric(lon), y = as.numeric(lat)),
size = 0.3) +
stat_density2d(data = data3,
aes(x = as.numeric(lon), y = as.numeric(lat),
fill = ..level.., alpha = ..level..),
size = 0.3, bins = 500, geom = "polygon") +
scale_fill_gradient(low = "yellow", high = "orange") +
scale_alpha(range = c(0, 0.3), guide = FALSE)
When I run it, he applies to every heat map the the last colour, in this case yellow-orange.
This is what I get:
I have been able add a facet based label, however, how do I make it label as the text:
"Mean = 0.235" instead of just "0.235"
Here's my ggplot, where the important part is geom_text:
ggplot(data = filter(season_melt,(HOUSEHOLD_ID_ANONYMISED %in% c(37218002754,37218032412, 38443537620))), aes(factor(HOUSEHOLD_ID_ANONYMISED), value)) +
geom_boxplot(aes(fill = factor(HOUSEHOLD_ID_ANONYMISED))) +
facet_wrap(~Season) +
theme(text = element_text(size=40), legend.position = "none") +
xlab("Household ID") +
ylab("Usage") +
geom_hline(data = mean_season, aes(yintercept = Mean), size = 1, colour = "blue", linetype = "dashed") +
geom_text(data = mean_season, aes(0,Mean,label = round(Mean,3), vjust = -1, hjust = -0.1), color = "blue", size = 11)
Here's a pic which shows the labels in each facet:
You have (at least) two options.
Create the appropriate character string
# Something like
geom_text(data = mean_season,
aes(0, Mean, label = sprintf('Mean = %0.3f', Mean),
vjust = -1, hjust = -0.1),
color = "blue", size = 11)
# or
geom_text(data = mean_season,
aes(0, Mean, label = paste('Mean = ',round(Mean, 3)),
vjust = -1, hjust = -0.1),
color = "blue", size = 11)
Use parse=TRUE in the call to geom_text. In this case you would need to construct an appropriate expression according to ?plotmath (and ?geom_text)
geom_text(data = mean_season, parse = TRUE
aes(0, Mean, label = paste('Mean ==',round(Mean, 3)),
vjust = -1, hjust = -0.1),
color = "blue", size = 11)
Option 2 will create a "nicer" looking expression when visualized.