Is it possible to draw a heatmap with circles instead of square in ggplot2? It would be neat to not only represent the values by a color gradient but also by the circle size.
I am thinking of a graph like this dot heatmap where also the circle sizes are alternated by their specific value. I already read myself into heatmapping with ggplot2 but couldn't find a solution. For heatmapping I alternated the example posted on learnr.wordpress.com to:
library(ggplot2)
library(plyr)
library(reshape2)
library(scales)
kreuz <- read.csv("http://datasets.flowingdata.com/ppg2008.csv")
kreuz.m <- melt(kreuz)
(p <- ggplot(kreuz.m, aes(Name, variable)) +
geom_tile(aes(fill = value), colour = "white") +
scale_fill_gradient2(breaks=waiver(), name="binding strength",
low ="white", mid= ("lightblue"), high = "steelblue", midpoint = 4))
base_size <- 10
p + theme_grey(base_size = base_size) +
theme(panel.grid.major = element_blank())+
labs(x = "Patient ID", y = "Phage Motives", title = "Cross Reactivity")+
scale_x_discrete(expand = c(0, 0)) +
scale_y_discrete(expand = c(0, 0)) +
theme(legend.position = "right", axis.ticks = element_blank(),
axis.text.x = element_text(size = base_size *0.8, angle = 270, hjust = 0,
colour = "grey50"))+
labs(x = "Patient ID", y = "Phagemotives", title = "cross reactivity")
I would be very greatful for some hints!
In this example size and colour both correspond with the variable value because it's the only variable numeric available in the kreuz.m dataset.
ggplot(kreuz.m, aes(Name, variable)) +
geom_point(aes(size = value, colour=value))
Related
I'm trying to adjust the point and line size independently in my legend. I'm wanting to be able to discern between the dashed and solid line while also having my point shapes be distinctive enough overtop of the line in the legend. Right now, I can't seem to figure out how to make the line smaller - I've figured out how to adjust the point size though. Any help/thoughts are all appreciated; definitely still a newbie. Thanks!
I'll post an image and code below:
Image of figure with points enhanced, but still can't get line to size correctly in the legend
- Chase
ggplot(df, aes(x = Psych.Distress.Sum, y = Likelihood.Max, color = Feedback)) +
geom_smooth(method = "lm", se = T, aes(linetype = Feedback)) +
geom_jitter(aes(shape = Feedback)) +
labs(x = "Psychological Distress", y = "Endorsement of Max's Feedback Strategy") +
apatheme +
theme(axis.title = element_text(face="bold")) +
theme(legend.text = element_text(face="bold")) +
theme(legend.position = c(0.87, 0.13)) +
scale_color_grey(end = .5) +
theme(legend.key.height= unit(.5, 'cm'),
legend.key.width= unit(1, 'cm')) +
guides(colour = guide_legend(override.aes = list(size= 3, linetype=0)))
This is tricky. Here's a hacky way using two plots that are overlaid on top of each other using patchwork. To prove that the data are aligned, I made the 2nd plot's text be semi-transparent red, but we could make it totally transparent with color #FF000000. This method is a little brittle, since the plots will come out of alignment if they have different ranges or different formats. But if we adjust for that, they line up perfectly with no extra fuss.
Your question didn't include any sample data so I used the mtcars data set.
library(patchwork)
library(ggplot2)
# This layer has the `geom_smooth` and black axis text
(a <- ggplot(mtcars, aes(x = wt, y = mpg, color = as.factor(am))) +
geom_smooth(method = "lm", se = T, aes(linetype = as.factor(am))) +
scale_color_grey(end = .5) +
guides(linetype = guide_legend(override.aes = list(size = 1.2))) +
labs(x = "Psychological Distress",
y = "Endorsement of Max's Feedback Strategy",
linetype = "Line legend", color = "Line legend") +
coord_cartesian(ylim = c(10, 35)) +
theme_classic() +
theme(axis.title = element_text(face="bold")) +
theme(legend.text = element_text(face="bold")) +
theme(legend.position = c(0.7, 0.8)))
# This layer has the `geom_jitter` and red semi-clear axis text
(b <- ggplot(mtcars, aes(x = wt, y = mpg, color = as.factor(am))) +
geom_jitter(aes(shape = as.factor(am))) +
scale_color_grey(end = .5) +
guides(shape = guide_legend(override.aes = list(size = 3))) +
coord_cartesian(ylim = c(10, 35)) +
labs(x = "", y = "",
color = "Point legend", shape = "Point legend") +
theme_classic() +
theme(plot.background = element_blank(),
panel.background = element_blank(),
axis.text = element_text(color = "#FF000055")) +
theme(legend.position = c(0.7, 0.55)))
a + inset_element(b, 0, 0, 1, 1, align_to = "full")
I have spent hours looking in the documentation and on StackOverflow, but no solution seems to solve my problem. When using ggplot I can't get the right text in the legend, even though it's in my dataframe. I have tried scale_colour_manual, scale_fill_manual with different values for labels= such as c("T999", "T888")", "cols".
Here is my code:
T999 <- runif(10, 100, 200)
T888 <- runif(10, 200, 300)
TY <- runif(10, 20, 30)
df <- data.frame(T999, T888, TY)
ggplot(data = df, aes(x=T999, y=TY, pointtype="T999")) +
geom_point(size = 15, colour = "darkblue") +
geom_point(data = df, aes(x=T888, y=TY), colour = 'red', size = 10 ) +
theme(axis.text.x = element_text(size = 20), axis.title.x =element_text(size = 20), axis.text.y = element_text(size = 20)) +
xlab("Txxx") + ylab("TY [°C]") + labs(title="temperatures", size = 15) +
scale_colour_manual(labels = c("T999", "T888"), values = c("darkblue", "red")) + theme(legend.position="topright")
Help would be very appreciated!
The tutorial #Henrik mentioned is an excellent resource for learning how to create plots with the ggplot2 package.
An example with your data:
# transforming the data from wide to long
library(reshape2)
dfm <- melt(df, id = "TY")
# creating a scatterplot
ggplot(data = dfm, aes(x = TY, y = value, color = variable)) +
geom_point(size=5) +
labs(title = "Temperatures\n", x = "TY [°C]", y = "Txxx", color = "Legend Title\n") +
scale_color_manual(labels = c("T999", "T888"), values = c("blue", "red")) +
theme_bw() +
theme(axis.text.x = element_text(size = 14), axis.title.x = element_text(size = 16),
axis.text.y = element_text(size = 14), axis.title.y = element_text(size = 16),
plot.title = element_text(size = 20, face = "bold", color = "darkgreen"))
this results in:
As mentioned by #user2739472 in the comments: If you only want to change the legend text labels and not the colours from ggplot's default palette, you can use scale_color_hue(labels = c("T999", "T888")) instead of scale_color_manual().
The legend titles can be labeled by specific aesthetic.
This can be achieved using the guides() or labs() functions from ggplot2 (more here and here). It allows you to add guide/legend properties using the aesthetic mapping.
Here's an example using the mtcars data set and labs():
ggplot(mtcars, aes(x=mpg, y=disp, size=hp, col=as.factor(cyl), shape=as.factor(gear))) +
geom_point() +
labs(x="miles per gallon", y="displacement", size="horsepower",
col="# of cylinders", shape="# of gears")
Answering the OP's question using guides():
# transforming the data from wide to long
require(reshape2)
dfm <- melt(df, id="TY")
# creating a scatterplot
ggplot(data = dfm, aes(x=TY, y=value, color=variable)) +
geom_point(size=5) +
labs(title="Temperatures\n", x="TY [°C]", y="Txxx") +
scale_color_manual(labels = c("T999", "T888"), values = c("blue", "red")) +
theme_bw() +
guides(color=guide_legend("my title")) # add guide properties by aesthetic
I would like to produce a plot using facet_wrap that has a different y scale for each row of the wrap. In other words, with fixed scales on the same row, free scales on different rows, with a fixed x scale. Free scales doesn't give me exactly what I'm looking for, nor does facet_grid. If possible, I'd like to avoid creating 2 separate plots and then pasting them together. I'm looking for a result like the plot below, but with a y scale max of 300 for the first row, and an y scale max of 50 in the second row. Thanks for any help!
Here is my code:
library(ggplot2)
library(reshape)
# set up data frame
dat <- data.frame(jack = c(150,160,170),
surgeon = c(155,265,175),
snapper = c(10,15,12),
grouper = c(5,12,50))
dat$island<-c("Oahu","Hawaii","Maui")
df<-melt(dat)
# plot
ggplot(df, aes(fill=variable, y=value, x=island)) +
geom_bar(width = 0.85, position= position_dodge(width=0.5),stat="identity", colour="black") +
facet_wrap(~variable, scales = "free_y",ncol=2) +
theme_bw() +
theme(strip.text = element_text(size=15, face="bold"))+
theme(legend.position="none")+
theme(panel.grid.major = element_line(colour = "white", size = 0.2))+
theme(panel.grid.minor = element_line(colour = "white", size = 0.5))+
theme(axis.text.x = element_text(angle = 90, hjust =1, vjust =0.5, size=18))+
labs(y = expression(paste("Yearly catch (kg)")))
Drawing on one of the lower ranked answers from the link Eric commented, you can add a layer that blends into the background to enforce the axes.
Here I created a second data frame (df2) that puts a single point at "Hawaii" and the max value you wanted (300 or 50) for the four variable/fish types. By manually setting the color of the geom_point white, it fades into the background.
library(ggplot2)
library(reshape)
# set up data frame
dat <- data.frame(jack = c(150,160,170),
surgeon = c(155,265,175),
snapper = c(10,15,12),
grouper = c(5,12,50))
dat$island<-c("Oahu","Hawaii","Maui")
df<-melt(dat)
#> Using island as id variables
df2 <- data.frame(island = rep("Hawaii",4), variable = c("jack","surgeon","snapper","grouper"),value = c(300,300,50,50))
ggplot(df, aes(fill=variable, y=value, x=island)) +
geom_bar(width = 0.85, position= position_dodge(width=0.5),stat="identity", colour="black") +
geom_point(data = df2, aes(x = island, y = value), colour = "white") +
facet_wrap(~variable, scales = "free_y",ncol=2) +
theme_bw() +
theme(strip.text = element_text(size=15, face="bold"))+
theme(legend.position="none")+
theme(panel.grid.major = element_line(colour = "white", size = 0.2))+
theme(panel.grid.minor = element_line(colour = "white", size = 0.5))+
theme(axis.text.x = element_text(angle = 90, hjust =1, vjust =0.5, size=18))+
labs(y = expression(paste("Yearly catch (kg)")))
I'm have made two separate scatter plots using ggplot2 and I need to combine them into one single plot. Each plot is for a population of lizards under three different treatments (backgrounds).
for each plot I have the following:
csMS = data.frame()
ellMS = data.frame()
centroidsMS = data.frame()
csplotMS = ggplot(csMS, aes(x = RG, y = GB, colour = Background)) + geom_point(size = 3, shape = 17) + #colour by background, circles size 3
geom_path(data = ell.AS, aes(x = RG, y = GB ,colour = Background), size = 1, linetype = 2) + #adding the ellipses
geom_point(data = centroidsMS, size = 3, shape = 17) + #added centroids
geom_errorbar(data = centroidsMS, aes(ymin = GB - se.GB, ymax = GB + se.GB), width = 0) + #add y error bars
geom_errorbarh(data = centroidsMS, aes(xmin = RG - se.RG, xmax = RG + se.RG), height = 0) +
theme_bw() + #white background
theme(axis.title.y = element_text(vjust = 2), axis.title.x = element_text(vjust = -0.3)) + #distance of axis titles from axis
theme(panel.border = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), #no grids
axis.line = element_line(colour = "black")) + #black axes
theme(text = element_text(size = 30)) + #font size
ylab("(G-B)/(G+B)") + xlab("(R-G)/(R+G)") + # Set text for axes labels
scale_colour_manual(values = c("black","#FF6600", "yellow1")) + #changed default colours
labs(colour = "Murray Sunset NP") +
theme(legend.title = element_text(size = "20")) + #changes the legend title
theme(legend.text = element_text(size = "20")) + #changes the legend title
theme(legend.key = element_blank()) + #removed little squares around legend symbols
theme(legend.direction = "horizontal", legend.position = c(.5, .85))
I tried
csASMS = csplotAS + csplotMS
but I get an error message: "Error in p + o : non-numeric argument to binary operator In addition: Warning message: Incompatible methods ("+.gg", "Ops.data.frame") for "+" "
I also tried
csASMS = grid.arrange(csplotAS, csplotMS)
but this places one plot on top of the other, but I need to combine both plots so that they are basically just one plot but with two separate legends as each plot has different conventions to indicate the different lizard populations.
Any help will be greatly appreciated.
****EDIT**** Dec 12/ 2014
I have managed to combine the two plots into one but still have the problem of the separate legends. To try to simplify the question and as per cdeterman's request I'm adding a simpler form of the code with some sample data:
data frames: p1 and p2
> p1
treatment x y
1 Black 1 1
2 Orange 2 2
3 Yellow 3 3
> p2
treatment x y
1 Black 4 4
2 Orange 5 5
3 Yellow 6 6
I used the following code to make a plot that includes both data frames:
plot = ggplot(p1, aes(x = x, y = y, colour = treatment)) + geom_point(size = 3) + #colour by background, circles size 3
theme_bw() + #white background
theme(axis.title.y = element_text(vjust = 2), axis.title.x = element_text(vjust = -0.3)) + #distance of axis titles from axis
theme(panel.border = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), #no grids
axis.line = element_line(colour = "black")) + #black axes
theme(text = element_text(size = 30)) + #font size
scale_colour_manual(values = c("black","#FF6600", "yellow1")) + #changed default colours
labs(colour = "p1") +
theme(legend.title = element_text(size = "20")) + #changes the legend title
theme(legend.text = element_text(size = "20")) + #changes the legend title
theme(legend.key = element_blank()) + #removed little squares around legend symbols
theme(legend.direction = "horizontal", legend.position = c(.33, 1)) +
# Now to add the second plot/ No need to code for axis titles, titles positions,etc b/c it's already coded in the first plot
geom_point(data = p2, aes(x = x, y = y, colour = treatment), size = 3, shape = 17)
This produces a graph with each data frame represented in a different symbol (circles for p1 and triangles for p2) but with only one combined legend with triangles superimposed over circles). How can I get two separate legends, one for each data frame?
Thank you!
After doing some research and trying different things I was able to solve PART of my problem. To add two plots together one needs to be plotter first and the other one on top of the first one using
geom.point()
my new code looks like this:
csplotASMS = ggplot(csAS, aes(x = RG, y = GB, colour = Background)) + geom_point(size = 3) + #colour by background, circles size 3
geom_path(data = ell.AS, aes(x = RG, y = GB ,colour = Background), size = 1, linetype = 1) + #adding the ellipses
geom_point(data = centroidsAS, size = 4) + #added centroids
geom_errorbar(data = centroidsAS, aes(ymin = GB - se.GB, ymax = GB + se.GB), width = 0) + #add y error bars
geom_errorbarh(data = centroidsAS, aes(xmin = RG - se.RG, xmax = RG + se.RG), height = 0) +
theme_bw() + #white background
theme(axis.title.y = element_text(vjust = 2), axis.title.x = element_text(vjust = -0.3)) + #distance of axis titles from axis
theme(panel.border = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), #no grids
axis.line = element_line(colour = "black")) + #black axes
theme(text = element_text(size = 30)) + #font size
ylab("(G-B)/(G+B)") + xlab("(R-G)/(R+G)") + # Set text for axes labels
scale_colour_manual(values = c("black","#FF6600", "yellow1")) + #changed default colours
labs(colour = "Alice Springs") +
theme(legend.title = element_text(size = "20")) + #changes the legend title
theme(legend.text = element_text(size = "20")) + #changes the legend title
theme(legend.key = element_blank()) + #removed little squares around legend symbols
theme(legend.direction = "horizontal", legend.position = c(.33, 1)) +
# Now to add the second plot/ No need to code for axis titles, titles positions,etc b/c it's already coded in the first plot
geom_point(data = csMS, aes(x = RG, y = GB, colour = Background), size = 3, shape = 17) +
geom_path(data = ell.MS, aes(x = RG, y = GB ,colour = Background), size = 1, linetype = 2) + #adding the ellipses
geom_point(data = centroidsMS, size = 4, shape = 17) + #added centroids
geom_errorbar(data = centroidsMS, aes(ymin = GB - se.GB, ymax = GB + se.GB), width = 0) + #add y error bars
geom_errorbarh(data = centroidsMS, aes(xmin = RG - se.RG, xmax = RG + se.RG), height = 0) #add x error bars
and the graph depicts a scatterplot for two populations, each with three treatments. Because tratments are the same for both populations I want to use the same colours but different symbols to denote the differences in populations. One population is circles and the other one is triangles.
Now, the part I can't answer yet is how to have two separate legends, one for each "plot". i.e. one for the circles and one for the triangles. At the moments there is a "combined legend showing triangles superimposed on circles. Each legend should have its own title.
Is it possible to draw a heatmap with circles instead of square in ggplot2? It would be neat to not only represent the values by a color gradient but also by the circle size.
I am thinking of a graph like this dot heatmap where also the circle sizes are alternated by their specific value. I already read myself into heatmapping with ggplot2 but couldn't find a solution. For heatmapping I alternated the example posted on learnr.wordpress.com to:
library(ggplot2)
library(plyr)
library(reshape2)
library(scales)
kreuz <- read.csv("http://datasets.flowingdata.com/ppg2008.csv")
kreuz.m <- melt(kreuz)
(p <- ggplot(kreuz.m, aes(Name, variable)) +
geom_tile(aes(fill = value), colour = "white") +
scale_fill_gradient2(breaks=waiver(), name="binding strength",
low ="white", mid= ("lightblue"), high = "steelblue", midpoint = 4))
base_size <- 10
p + theme_grey(base_size = base_size) +
theme(panel.grid.major = element_blank())+
labs(x = "Patient ID", y = "Phage Motives", title = "Cross Reactivity")+
scale_x_discrete(expand = c(0, 0)) +
scale_y_discrete(expand = c(0, 0)) +
theme(legend.position = "right", axis.ticks = element_blank(),
axis.text.x = element_text(size = base_size *0.8, angle = 270, hjust = 0,
colour = "grey50"))+
labs(x = "Patient ID", y = "Phagemotives", title = "cross reactivity")
I would be very greatful for some hints!
In this example size and colour both correspond with the variable value because it's the only variable numeric available in the kreuz.m dataset.
ggplot(kreuz.m, aes(Name, variable)) +
geom_point(aes(size = value, colour=value))