I am drawing a map with ggplot using a shape file. Then I add arcs using geom_line. The arcs are colored according to their type (oneway or twoway) and then I add nodes using geom_point. The nodes are colored according to their type (Origin, Destination, Node, Parking lot). I want to have two different legends: one for the node types and one for the arc types. Unfortunately, ggplot merges the legends and produces just one legend.
Here is the code (sorry that I can't provide a workable example. I can't send the shape files):
cityplot <- ggplot(data = s_zurich, aes(x = long, y = lat, group = id), fill = "white") +
geom_polygon(data = s_zurich, fill = "white") +
ylab("") + xlab("") +
theme(axis.text.x = element_blank(), axis.text.y = element_blank(), axis.ticks = element_blank())
cityplot_arcs <- cityplot +
geom_line(data = allarcs, aes(x = X1, y = X2, group = Id, colour = Direction), size = 1) +
xlab("") + ylab("")
cityplot_arcs_nodes <- cityplot_arcs + geom_point(aes(x = lon, y = lat, colour = Type), shape = 15, size = 4, inherit.aes = FALSE, data = allnodes) +
theme(legend.position = "none")
Any help would be appreciated.
Here is a possible workaround. If you can keep your geom_polygon fill out of the aes() call - as looks to be the case above, then you can use a filled shape for the point (21 is a circle) and set the fill attribute rather than the color in the aes() call. See below:
mock_data<-
data.frame(x=sample(1:10,20,T),
y=sample(1:10,20,T),
direction=sample(c("1way","2way"),20,T),
type=sample(c("origin","destination","node","lot"),20,T))
ggplot(mock_data) +
geom_polygon(aes(x=c(0,12,12,0),y=c(0,0,12,12),id=c(1,1,1,1)),fill="white") +
geom_point(aes(x=x,y=y,fill=type),size=10,shape=21) +
geom_line(aes(x=x,y=y,color=direction),size=2) +
scale_fill_brewer(palette="Greens") + scale_color_brewer(palette="Set1")
Failing that, you can plot a mock legend only using ggplot() and use grid.arrange() to plot it next to your graph minus the default legend. Let me know in the comments if you need help with that.
Related
I'm using ggplot2 for map plots in R. How do I add a legend entry for a layer without a scale, just for a uniform color:
geom_polygon(data = watercourses, fill = "#0055aa", alpha = .5)
I just want to have the item title "Watercourses" and a color block representing the correct fill color. How does this work? So far, I only figured out how I can include scales to the legend.
Thank you!
EDIT: Here's an example with the NC dataset.
Map without centroids in legend
library(sf)
library(ggplot2)
demo(nc)
nc_centroids <- st_centroid(nc)
ggplot(nc) +
geom_sf(aes(fill = BIR74)) +
scale_fill_gradient(low = "white", high = "red") +
geom_sf(data = nc_centroids, color = "blue") +
coord_sf()
Wrong usage of aes() for legend
ggplot(nc) +
geom_sf(aes(fill = BIR74)) +
scale_fill_gradient(low = "white", high = "red") +
geom_sf(data = nc_centroids, aes(color = "blue")) +
coord_sf()
Trying to add the centroids to the legend (based on the answer of r2evans, https://stackoverflow.com/a/75346358/4921339)
ggplot(nc) +
geom_sf(aes(fill = BIR74)) +
scale_fill_gradient(low = "white", high = "red") +
geom_sf(data = nc_centroids, aes(color = "County centroids")) +
scale_fill_manual(name = "Centroids", values = c("County centroids" = "blue"))
coord_sf()
Throws the following messages and an error:
Scale for fill is already present.
Adding another scale for fill, which will replace the existing scale.
Error: Continuous value supplied to discrete scale
In my original case I use sp package instead of sf, but the messages and error thrown in the end are the same.
I think I did not yet understand how things work here, unfortunately. Any helping hints are highly appreciated.
If you place your fill in an aes(.), it will create a legend. Since you want a specific color, I suggest also adding scale_fill_manual:
ggplot(mtcars[-(1:3),], aes(mpg, disp)) +
geom_point() +
# placeholder for your `geom_polygon`:
geom_point(data = mtcars[1:3,], aes(fill = "something"), alpha = 0.5) +
scale_fill_manual(name = "something else", values = c("something" = "#0055aa"))
Perhaps this to add your blue points:
ggplot(nc) +
geom_sf(aes(fill = BIR74)) +
scale_fill_gradient(low = "white", high = "red") +
geom_sf(data = transform(nc_centroids, col = "County centroids"), aes(colour = col)) +
coord_sf() +
scale_colour_manual(name = NULL, values = c("County centroids" = "blue"))
EDIT by #winnewoerp: Explanation of how it works, for those who have problems understanding it all (like me until now...):
Add an extra column to the data frame with a unique value to be used within the legend, this can be done e.g. using the transform() function like in the given example or like df$col <- "Column unique value" prior to ggplot().
The (sole?) advantage to using transform is that there is no need to alter the original data, which might affect other processes on it (outside of this image). One disadvantage to doing it this way is that one must hard-code the "Column unique value" in both the transform and the scale_colour_manual, below.
Use scale_colour_manual() to add the legend item (blue colour example):
scale_colour_manual(
name = "Legend title",
values = c("Column unique value" = "blue")
)
I have a plot with a discrete colorscheme (109 different levels) and a colorstep legend.
The legend then shows all ticks for each color. How can I only show a few of the labels and ticks in the legend rather than all?
Plot 1 shows the legend when the labels are still there
Plot 2 shows the legend without the labels. I want to show only certain labels in the legend, to make it actually understandable (10 different values rather than 100). How do I do that?
My code is below, I am clearly doing something wrong, I just do not know what it is.
tt <- ggplot() +
# first layer: all countries, no fill, no white outlines
geom_polygon(data = maps2,
aes(x = long, y = lat, group = group), fill="grey", show.legend = F, size = 0.1) +
# second layer: only countries with a fill
geom_polygon(data = test,
aes(x = long, y = lat, group = group, fill = as.factor(tally)), show.legend = T)+
scale_fill_viridis_d(option="D", na.value = NA)+
facet_grid(~IO)+
theme( strip.text.x = element_blank())
tt + guides(fill=guide_colorsteps(label = F, title=element_blank())
I have the dataset below:
Database<-c("Composite","DB","TC","RH","DGI","DCH","DCH","DCH","LDP")
Unique_Drugs<-c(12672,5130,1425,3090,6100,2019,250,736,1182)
Unique_Targets<-c(3987,2175,842,2308,2413,1441,198,327,702)
db<-data.frame(Database,Unique_Drugs,Unique_Targets)
and I would like to create a dodged bar chart like the picture below:
This plot came from a dataframe like:
The difference is that in the x-axis I want the 7 unique Database names and the fill argument should be the Unique_Drugs and Unique_Targets in order to create 2 colored bars that will display their values. Im not sure how to make it work.
My code is:
p <- ggplot(data = db, aes(Database)) +
geom_bar(position = position_dodge(preserve = "single"), stat="count", aes(fill = colnames(db[2:4])), color = "black")+
coord_flip()+
theme(legend.position="top",
legend.title=element_blank(),
axis.title.x=element_text(size=18, face="bold", color="#000000"), # this changes the x axis title
axis.text.x = element_text(size=14, face="bold", color="#000000"), #This changes the x axis ticks text
axis.title.y=element_text(size=18, face="bold", color="#000000"), # this changes the y axis title
axis.text.y = element_text(size=14, face="bold", color="#000000"))+ #This changes the y axis ticks text
labs(x = "Database") +
labs(y = "Value") +
scale_x_discrete(limits = rev(factor(Database))) +
scale_fill_manual("Databases", values = c("tomato","steelblue3"))
Here's one way to achieve what you want:
library(reshape2)
ggplot(melt(db), aes(x = Database, y = value, fill = variable)) +
geom_col(position = "dodge") + ylab(NULL) + theme_minimal() +
scale_fill_discrete(NULL, labels = c("Drugs", "Targets"))
If you wanted a bar plot only for drugs, there would be no need for melt as you could use y = Unique_Drugs to specify the bar heights (note that since we have heights we use geom_col). In this case, however, we want to specify two kinds of heights. Your words that fill argument should be the Unique_Drugs and Unique_Targets precisely suggest that we need some transformations because ggplot doesn't accept two variables for the same aesthetic. So, using melt we get all the heights as a single variable and get a single variable for fill.
I've got a data frame with three variables, location, price, and varname.
I'd like to use ggplot2's geom_tile to make a heat map of sorts. This plot almost looks like a bar chart, but I prefer geom_tile because I like the values, big or small, to be allocated the same amount of physical space on the plot. My code almost gets me there.
The first problem's that I can't format the plot so to get rid of all the white space to the left and right of my pseudo-bar. The second problem's that I can't remove the Price legend below the plot, because I'd like Price only to feature in the legend above the plot.
Thanks for any help!
Starting point (df):
df <- data.frame(location=c("AZ","MO","ID","MI"),price=c(1380.45677,1745.1245,12.45652,1630.65341),varname=c("price","price","price","price"))
Current code:
library(ggplot2)
ggplot(df, aes(varname,location, width=.2)) + geom_tile(aes(fill = price),colour = "white") + geom_text(aes(label = round(price, 3))) +
scale_fill_gradient(low = "ivory1", high = "green") +
theme_classic() + labs(x = "", y = "") + theme(legend.position = "none") + ggtitle("Price")
Don't set the width to 0.2.
Use theme to disable the labels and ticks.
You might want to use coord_equal to get nice proportions (i.e. squares). expand = FALSE gets rid of all white space.
.
ggplot(df, aes(varname, location)) +
geom_tile(aes(fill = price), colour = "white") +
geom_text(aes(label = round(price, 3))) +
scale_fill_gradient(low = "ivory1", high = "green") +
theme_classic() + labs(x = "", y = "") +
theme(legend.position = "none", axis.text.x = element_blank(), axis.ticks.x = element_blank()) +
ggtitle("Price") +
coord_equal(expand = FALSE)
I am trying to create a map with barplots for each state. I used geom_subplot2d. I am having a couple of issues and I was hoping somebody can help fix them
The border color I want it to be black but it is red no matter what value I use.
The color of the legend items (barplot) is also absorbed by each state. Is there a way that it can be separate?
Here is the code that produces the diagram:
p <- ggplot() +
geom_polygon(data = total,
aes(x = x, y = y, group = region, colour = "black",
fill = cut(eval(as.symbol(var1)), 10))) +
scale_fill_brewer(palette = "Blues")
testplot <- p +
geom_subplot2d(aes(long, lat, subplot = geom_bar(aes(yy, ..count.., fill = yy))),
bins = c(25,20), ref = NULL, width = rel(0.5), data = simdat) +
scale_fill_brewer(palette = "YlGn")
print(testplot)