I am attempting to make a GIF of several different maps, showing how crime moves across the city at different times in the day. In order to do this, I am making several different stat_density2d() plots, one plot for each time interval. Here's the code:
data <- read.csv(".../CrimeLocationAndTime.csv",
stringsAsFactors = FALSE)
# Get base map layer
denver = c(lon = -104.9903, lat = 39.7392)
denver_map = get_map(location = denver, zoom = 13, color = "bw")
# Get data slices
twoAMTimeSlice <- data[data$time == "2:00 AM",]
tenAMTimeSlice <- data[data$time == "10:00 AM",]
# Create density map
ggmap(denver_map, extent = "panel", maprange=FALSE) +
stat_density2d(data = twoAMTimeSlice,
aes(x = longitude, y = latitude, fill = ..level.., alpha = ..level..),
size = 0.1, bins = 16, geom = 'polygon') +
scale_fill_gradient(low = "green", high = "red", limits=c(0,2000)) + # Color scale
scale_alpha(range = c(0.1, 0.4), guide = "legend") + # Here is the alpha scale
geom_text(label = twoAMTimeSlice$time[1], x = -104.95, y=39.775) +
theme(plot.title = element_text(size = rel(1.5), vjust = 1),
axis.title = element_blank(),
text = element_text(size = 12)) +
labs(title = "Criminal Occurrences by Time of Day")
So here's my problem: I need my alpha scale to be consistent across all of my maps. Currently, if I make the graphs across different times with different amounts of crime, the alpha scale does not stay consistent. This is apparent in these pictures:
Observe how the green color in this picture is very transparent and the red is more opaque. This is the correct scale that I would like to apply to all maps.
Here, observe how the green is very opaque. You can also see the legend change from the last picture. This is bad. I would like the green in this picture to be just as opaque as the last one.
I have achieved this consistency of scale for the colors, using the limits argument to scale_fill_gradient. However, this argument gives wonky results when applied to scale_alpha.
The solution was changing the limits to
limits=c(0, 2000)
(answered by OP in comments)
Related
I want to make the Girls have the dashed trendline and the Boys have a solid trendline. I'd also like to remove the box around the graph, save the y and x-axis lines, and the shading behind the shapes on the key. I am using ggplot2 in R.
dr <- ggplot(DATASET,
aes(x=EC,
y=sqrt_Percent.5,
color=Sex1M,
shape=Sex1M,
linetype=Sex1M)) +
geom_point(size= 3,
aes(shape=Sex1M,
color=Sex1M)) +
scale_shape_manual(values=c(1,16))+
geom_smooth(method=lm,
se=FALSE,
fullrange=TRUE) +
labs(x="xaxis title",
y = "yaxis title",
fill= "") +
xlim(3,7) +
ylim(0,10) +
theme(legend.position = 'right',
legend.title = element_blank(),
panel.border = element_rect(fill=NA,
color = 'white'),
panel.background = NULL,
legend.background =element_rect(fill=NA,
size=0.5,
linetype="solid")) +
scale_color_grey(start = 0.0,
end = 0.4)
Current Graph
There is quite something going on in your visualisation. One strategy to develop this is to add layer and feature by feature once you have your base plot.
There a different ways to change the "sequence" of your colours, shapes, etc.
You can do this in ggplot with one of the scale_xxx_manual layers.
Conceptually, I suggest you deal with this in the data and only use the scales for "twisting". But that is a question of style.
In your case, you use Sex1M as a categorical variable. There is a built in sequence for (automatic) colouring and shapes. So in your case, you have to "define" the levels in another order.
As you have not provided a representative sample, I simulate some data points and define Sex1M as part of the data creation process.
DATASET <- data.frame(
x = sample(x = 2:7, size = 20, replace = TRUE)
, y = sample(x = 0.2:9.8, size = 20, replace = TRUE)
, Sex1M = sample(c("Boys", "Girls"), size = 20, replace = TRUE )
Now let's plot
library(dplyr)
library(ggplot2)
DATASET <- DATASET %>%
mutate(Sex1M = factor(Sex1M, levels = c("Boys","Girls)) # set sequence of levels: boys are now the first level aka 1st colour, linetype, shape.
# plot
ggplot(DATASET,
aes(x=x, # adapted to simulated data
y=y, # adapted to simulated data
color=Sex1M, # these values are now defined in the sequence
shape=Sex1M, # of the categorical factor you created
linetype=Sex1M) # adapt the factor levels as needed (e.g change order)
) +
geom_point(size= 3,
aes(shape=Sex1M,
color=Sex1M)) +
scale_shape_manual(values=c(1,16))+
geom_smooth(method=lm,
se=FALSE,
fullrange=TRUE) +
labs(x="xaxis title",
y = "yaxis title",
fill= "") +
xlim(3,7) +
ylim(0,10) +
theme(legend.position = 'right',
legend.title = element_blank(),
panel.border = element_rect(fill=NA,
color = 'white'),
panel.background = NULL,
#------------ ggplot is not always intuitive - the legend background the panel
# comprising the legend keys (symbols) and the labels
# you want to remove the colouring of the legend keys
legend.key = element_rect(fill = NA),
# ----------- that can go. To see above mentioned difference of background and key
# set fill = "blue"
# legend.background =element_rect(fill = NA, size=0.5,linetype="solid")
) +
scale_color_grey(start = 0.0,
end = 0.4)
The settings for the background panel make the outer line disappear in my plot.
Hope this helps to get you started.
similar to a couple questions, but I have a couple of issues that come up that are unique. (I tried using code from here but it doesn't work for me due to potentially using ggmap instead of ggplot).
I am trying to plot a map with point color changes based on whether plants are infected (1) or not infected (0) with a pathogen. Even better, I would like to change color of points (pathogen status) and shape of points based on plant species (there are 2).
My columns are
Sample name, plant species (a or b), lat, lon, pathogen status (0 or 1)
created a map (just an example coordinate used for how i would make the map)
map <- get_googlemap(center = c(lon = -111.348284, lat = 38.484637), zoom = 15, maptype = "satellite")
then here's the code. it works as is, but i cannot figure out where to put the conditional statement. I used colors from a national parks pallete.
ggtitle("Distribution of pathogen") +
theme_void() +
geom_point(data = data, mapping = aes(x = Longitude, y = Latitude), color = "#7397CB", size=1) +
theme(
plot.title = element_text(colour = "#554C6C") ,
panel.border = element_rect((colour = "#70646E"), fill=NA, size=2)
)
If this has been answered before (which I have checked other questions, but none relate to ggmap, or that x and y values are not what i want to be the reason for color change) please link!
Thanks -T
Use color as an aesthetic and set to pathogen status, and add shape aesthetic set to species:
ggtitle("Distribution of pathogen") +
theme_void() +
geom_point(data = data, mapping = aes(x = Longitude, y = Latitude,
color=PathogenStatus, shape=Species), size=1) +
theme(
plot.title = element_text(colour = "#554C6C") ,
panel.border = element_rect((colour = "#70646E"), fill=NA, size=2)
)
I am a newbie for stack Overflow and r language.
Here is my problem.
I now have a dataframe with one variable called Type and other 14 variables whose correlation matrix heatmap needed to be calculated.
origin dataset
I already have an overall format using ggplot2, and the theme is default theme_grey but fine for me to view. The code is :
m<- melt(get_lower_tri(round(cor(xrf[3:16], method = 'pearson', use = 'pairwise.complete.obs'), 2)),na.rm = TRUE)
ggplot(m, aes(Var1, Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(low = 'skyblue4',
high = 'coral2',
mid = 'white',
midpoint = 0,
limit = c(-1, 1),
space = "Lab",
name = 'Person\nCorrelation') +
theme_grey()+
coord_fixed() +
theme(axis.title = element_blank())
The result is fine and the background looks good to view.
But when I managed to generate a grouped correlation matrix heatmap, I found that no matter how hard I tried (using theme(panel.background = element_rect()) or theme(panel.background = element_blank())), the subplot backgrounds won’t change and remain this ugly grey which is even different from the overall one.
Here is my code:
Type = rep(c('(a)', '(b)', '(c)','(d)', '(e)', '(f)', '(g)', '(h)', '(i)', '(j)'), each = 14^2)
# Get lower triangle of the correlation matrix
get_lower_tri<-function(x){
x[upper.tri(x)] <- NA
return(x)
}
df2 <- do.call(rbind, lapply(split(xrf, xrf$Type),
function(x) melt(get_lower_tri(round(cor(x[3:16], method = 'pearson', use = 'pairwise.complete.obs'), 2)),na.rm = FALSE)))
my_cors <- cbind(Type,df2)
my_cors %>%
ggplot(aes(Var1, Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(low = 'skyblue4',
high = 'coral2',
mid = 'white',
midpoint = 0,
limit = c(-1, 1),
space = "Lab",
name = 'Person\nCorrelation') +
theme_grey()+
coord_fixed() +
theme(axis.title = element_blank(),
panel.background = element_rect(fill = 'grey90',colour = NA))+
facet_wrap("Type",ncol = 5, nrow = 2)
Isn’t the facet subplot backgrounds the same as the overall one if using the same theme? And how can I change it?
Update:sorry! It’s my first time to raise a question and it’s not a good one!
xrf is my original dataset...But now I have figured out why thanks to Tjebo and those who comment my faulty questions.It’s very instructive to me!!
scale_fill_gredient2(...,na.value = 'transparent') will solve it.The default value of this parameter is "grey50" which I took as the background color.
I am truly sorry for asking such a silly question, and I really really appreciate you guys’s nice comment for a rookie! Thank you guys!
I have a heat map of US data by state (using dummy data), and I'm trying to get it to run a color gradient continuously from dark red to light red from [0,50] and from light green to dark green from (50,100].
If I try using one gradient from red to green it gets quite brown in the middle and if I run from red to white to green it becomes tough to read with the middle colors. Can anyone help me find a way to perform two continuous color gradients on the same map?
Here is my code:
library(ggplot2)
library(fiftystater)
library(colorplaner)
library(RColorBrewer)
# prepare data frame
data("fifty_states")
dft <- data.frame(state=tolower(rownames(USArrests)), USArrests)
names(dft)[names(dft)=='Murder'] <- 'Var1'
dft<-dft[,-c(3:5)]
# create data
dft$Var1 <- runif(50,0, 100)
# map to each state's data
p <- ggplot(dft, aes(map_id = state)) +
# map points to the fifty_states shape data
geom_map(aes(fill = Var1), map = fifty_states, color = 'gray') +
expand_limits(x = fifty_states$long, y = fifty_states$lat) +
coord_map() +
scale_x_continuous(breaks = NULL) +
scale_y_continuous(breaks = NULL) +
labs(x = "", y = "") +
theme(legend.position = "bottom",
panel.background = element_blank())
p+ fifty_states_inset_boxes()
Going from red to white to green continuously
pc <- p+scale_fill_gradient2(low='darkred',
mid = 'white',
high='darkgreen',
midpoint = 50)
pc + fifty_states_inset_boxes() + theme(legend.position = "right")
I found this palette stuff online, but am totally new to it and wasn't able to find a solution playing with it. But it could be useful and I just don't know enough about it.
#TEST
palette <- colorRampPalette(rev(brewer.pal(11,"Spectral")))
pcn <- p+scale_fill_gradientn(colours = palette(4))
pcn + fifty_states_inset_boxes() + theme(legend.position = "right")
Here is the idea by Andrew Gustar explained a bit further:
pc <- p + scale_fill_gradientn(colors = c("darkred", "tomato1","palegreen", "darkgreen"),
values = scales::rescale(c(min(dft$Var1),
(max(dft$Var1)-min(dft$Var1))/3,
(max(dft$Var1)-min(dft$Var1))*2/3,
max(dft$Var1))))
pc + fifty_states_inset_boxes() + theme(legend.position = "right")
This is equivalent to: values = c(0, 1/3, 2/3, 1)
scale_fill_gradientn takes a vector of any number of colors and maps them to the values in your data - you can control the mapping with the values argument which takes the range 0 - 1. scales::rescale scales an arbitrary range vector to 0 - 1 range.
It's can be visually pleasing to use
quantile(dft$Var1, seq(0, 1, length.out = n)) #n depending on the number of colors
to define the values. Example:
pc <- p+scale_fill_gradientn(colors = c("darkred", "tomato1","palegreen", "darkgreen"),
values = scales::rescale(quantile(dft$Var1, seq(0, 1, length.out=4))))
pc + fifty_states_inset_boxes() + theme(legend.position = "right")
Finally, as Andrew Gustar suggested values = c(0, 0.5, 0.5001, 1)) would provide the gradient you asked in the OP: from dark red to light red from [0,50] and from light green to dark green from (50,100]. Giving:
I'm really struggling with the size and color parameters of geom_path in ggplot2. Let me share my data and code (both short) with you first, then show the plot I'm getting, then explain what plot I am trying to obtain. I'm really confused with this output right now:
# the data - x and y coordinates to plot
x_loc = c(39.29376, 39.44371, 39.59578, 39.7439, 39.88808, 40.18122,
40.92207, 41.91831, 42.09564, 42.27909, 81.77751, 81.79779, 81.81031,
81.81723, 81.81997, 81.81846)
y_loc = c(21.02953, 20.91538, 20.80633, 20.69479, 20.58158, 20.37095,
19.87498, 19.38372, 19.31743, 19.26005, 35.55103, 35.64354, 35.7384,
35.82535, 35.9067, 35.98656)
# creating the factor with which to base size and color off of
end = length(x_loc)
distances = sqrt(((x_loc[2:end] - x_loc[1:(end-1)]) ^ 2) + ((y_loc[2:end] - y_loc[1:(end-1)]) ^ 2))
my_colors = c('black', ifelse(distances > 0.5, 'red', 'black'))
# and now for my plot
ggplot() +
geom_point(aes(x = x_loc, y = y_loc)) +
geom_path(aes(x = x_loc, y = y_loc, col = as.factor(my_colors), size = as.factor(my_colors)),
alpha = 1) +
scale_color_manual(values = c("black", "red")) +
scale_size_manual(values = c(1.5, 0.45))
Here is the output plot I'm getting, incase you haven't run my code:
Here's what I'm getting, but it's not what I want. My objective here is to plot the coordinate points with lines connecting the points, so I use separate layers for geom_point() and geom_path(). However, for very long lines (long distances between consecutive coordinates), measured in the distances vector, I would like the line color to be red and for the line to be thin. For the short distances, I would like the line color to be black and for the line to be thicker.
What's wrong with my plot above is that the long black line should not be there. There's an additional black line plotting that shouldn't appear either (where the other red line is).
(It appears that by splitting the coordinates into groups (groups by size and by color, both set using the my_colors vector), the geom_path is creating two separate paths for two separate groups of points, each of which has the respective size and colors correct. However, this results in the wrong plot)
Let me know if I'm not explaining this correctly. I really want to get to the bottom of this, somehow. I'll work now on manually creating a plot similar to what I would want, and will edit shortly with it!
Thanks!
EDIT: Here's what I'm hoping to get:
which was created by cheating somewhat (cheating in the sense that I can get away with this for 16 coordinates, but not for 100K), using the following 5 geom_path layers:
ggplot() + geom_point(aes(x = x_loc, y = y_loc)) +
geom_path(aes(x = x_loc[1:6], y = y_loc[1:6]),
color = 'black',
size = 1.5,
alpha = 1) +
geom_path(aes(x = x_loc[6:8], y = y_loc[6:8]),
color = 'red',
size = 0.45,
alpha = 1) +
geom_path(aes(x = x_loc[8:10], y = y_loc[8:10]),
color = 'black',
size = 1.5,
alpha = 1) +
geom_path(aes(x = x_loc[10:11], y = y_loc[10:11]),
color = 'red',
size = 0.45,
alpha = 1) +
geom_path(aes(x = x_loc[11:16], y = y_loc[11:16]),
color = 'black',
size = 1.5,
alpha = 1)
I think I solved this myself - for anybody working on this, has to do with groupings. I will edit this with a solution shortly!
EDIT:
ggplot() +
geom_point(aes(x = x_loc, y = y_loc)) +
geom_path(aes(x = x_loc, y = y_loc, col = my_colors, size = my_colors, group = my_group),
alpha = 1) +
scale_color_manual(values = c("black", "red")) +
scale_size_manual(values = c(1.5, 0.45))
this gets the job done!, needed to group everything into the same group before splitting up the colors and sizes