Combine coord_proj and geom_raster - r

I am looking for a means of plotting raster data (using ggplot and geom_raster) on a small scale map. I would like to use ggalt and coord_proj to 'zoom-in' on particular regions of the shapefile, but I run into the error geom_raster only works with Cartesian coordinates
ggplot() +
geom_polygon(data = land_df, aes(long, lat, group = group), fill = 'grey25')+
geom_raster(data = df, aes(lon_bin, lat_bin, fill = sum_hours)) +
coord_proj(xlim = c(-67, -63),ylim = c(0, 9))
Is there another simple means of generating zoomed in raster maps using coord_proj and avoiding this restriction that geom_raster only works with Cartesian coordinates?
The other options I can think of is to generate individual shapefiles for each 'zoomed-in' region, but I am plotting many of these rasters and would rather not have to generate individual shapefiles for each and instead use coord_proj to programmatically specify raster map limits.
Thanks

I think you need to use geom_tile() instead of geom_raster(). geom_raster() internally uses a rasterGrob, which is a bitmap that can only be scaled linearly. Hence the limitation to Cartesian coordinate systems. geom_tile() draws individual rectangles which can be transformed into any coordinate system.
I don't have your dataset, but I can show a very simple example:
df <- data.frame(x = 1:100) # a very simple dataset
p_raster <- ggplot(df, aes(x, fill = x, y = 0)) +
geom_raster() +
scale_fill_distiller()
p_raster
p_raster + coord_polar()
## Error: geom_raster only works with Cartesian coordinates
Now with geom_tile():
# for geom_tile(), map both fill and color to avoid drawing artifacts
p_tile <- ggplot(df, aes(x, color = x, fill = x, y = 0)) +
geom_tile() +
scale_fill_distiller() +
scale_color_distiller()
p_tile
p_tile + coord_polar()

Related

How to clip an interpolated layer in R so it does not extend past data boundaries

I am trying to display a cross-section of conductivity in a lagoon environment using isolines. I have applied interp() and stat_contour() to my data, but I would like to clip the interpolated output so that it doesn't extend past my data points. This way the bathymetry of the lagoon in the cross-section is clear. Here is the code I have used so far:
cond_df <- read_csv("salinity_profile.csv")
di <- interp(cond_df$stop, cond_df$depth, cond_df$conductivity,
xo = seq(min(cond_df$stop), max(cond_df$stop), length = 200),
yo = seq(min(cond_df$depth), max(cond_df$depth), length = 200))
dat_interp <- data.frame(expand.grid(x=di$x, y=di$y), z=c(di$z))
ggplot(dat_interp) +
aes(x=x, y=y, z=z, fill=z)+
scale_y_reverse() +
geom_tile()+
stat_contour(colour="white", size=0.25) +
scale_fill_viridis_c() +
theme_tufte(base_family="Helvetica")
Here is the output:
interpolated plot
To help clarify, here is the data just as a geom_point() graph, and I do not want the interpolated layer going past the lower points of the graph:
cond_df%>%
ggplot(mapping=aes(x=stop, y=depth, z=conductivity, fill=conductivity)) +
geom_point(aes(colour = conductivity), size = 3) +
scale_y_reverse()
point plot
You can mask the unwanted region of the plot by using geom_ribbon.
You will need to generate a data.frame with values for the max depth at each stop. Here's one somewhat inelegant way to do that:
# Create the empty data frame for all stops
bathymetry <- data.frame(depth = as.numeric(NA),
stop = unique(cond_df$stop))
# Find the max depth for each stop
for(thisStop in bathymetry$stop){
bathymetry[bathymetry$stop==thisStop, "depth"] <- max(cond_df[cond_df$stop==thisStop, "depth"])
}
Then, you can add the geom_ribbon as the last geom of your plot, like so
geom_ribbon(data=bathymetry, aes(x=stop, ymin=depth, ymax=max(cond_df$depth)), inherit.aes = FALSE)

Unwanted Horizontal Lines in Map Projection in R

A few lines of code to expose my problem. When I work with a map of
the world and I introduce a projection, I always end up with some
weird looking horizontal lines.
Please have a look at
https://www.rdocumentation.org/packages/ggplot2/versions/1.0.0/topics/coord_map
from where I take the example for New Zeland
library(ggplot2)
nz <- map_data("nz")
# Prepare a map of NZ
nzmap <- ggplot(nz, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black")
# Plot it in cartesian coordinates
nzmap
# With correct mercator projection
nzmap + coord_map()
which works beautifully. Now let us do the same with the world
world <- map_data("world")
# Prepare a map of the world
worldmap <- ggplot(world, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black")
# Plot it in cartesian coordinates
worldmap
##but the following is a disaster!
# With correct mercator projection
worldmap + coord_map()
I see this issue of the horizontal lines with a projection has been
going on for quite a while, but I was able to find only seasoned posts
and I had assumed this was fixed long ago.
Please find below my sessionInfo.
Is there any solution to this? Is it still an open bug?
This is a pretty common problem in ggplot, but happily it is easily fixed:
worldmap + coord_map(xlim=c(-180,180))
produces
solution from: Why does coord_map produce a weird output?

3-variables plotting heatmap ggplot2

I'm currently working on a very simple data.frame, containing three columns:
x contains x-coordinates of a set of points,
y contains y-coordinates of the set of points, and
weight contains a value associated to each point;
Now, working in ggplot2 I seem to be able to plot contour levels for these data, but i can't manage to find a way to fill the plot according to the variable weight. Here's the code that I used:
ggplot(df, aes(x,y, fill=weight)) +
geom_density_2d() +
coord_fixed(ratio = 1)
You can see that there's no filling whatsoever, sadly.
I've been trying for three days now, and I'm starting to get depressed.
Specifying fill=weight and/or color = weight in the general ggplot call, resulted in nothing. I've tried to use different geoms (tile, raster, polygon...), still nothing. Tried to specify the aes directly into the geom layer, also didn't work.
Tried to convert the object as a ppp but ggplot can't handle them, and also using base-R plotting didn't work. I have honestly no idea of what's wrong!
I'm attaching the first 10 points' data, which is spaced on an irregular grid:
x = c(-0.13397460,-0.31698730,-0.13397460,0.13397460,-0.28867513,-0.13397460,-0.31698730,-0.13397460,-0.28867513,-0.26794919)
y = c(-0.5000000,-0.6830127,-0.5000000,-0.2320508,-0.6547005,-0.5000000,-0.6830127,-0.5000000,-0.6547005,0.0000000)
weight = c(4.799250e-01,5.500250e-01,4.799250e-01,-2.130287e+12,5.798250e-01,4.799250e-01,5.500250e-01,4.799250e-01,5.798250e-01,6.618956e-01)
any advise? The desired output would be something along these lines:
click
Thank you in advance.
From your description geom_density doesn't sound right.
You could try geom_raster:
ggplot(df, aes(x,y, fill = weight)) +
geom_raster() +
coord_fixed(ratio = 1) +
scale_fill_gradientn(colours = rev(rainbow(7)) # colourmap
Here is a second-best using fill=..level... There is a good explanation on ..level.. here.
# load libraries
library(ggplot2)
library(RColorBrewer)
library(ggthemes)
# build your data.frame
df <- data.frame(x=x, y=y, weight=weight)
# build color Palette
myPalette <- colorRampPalette(rev(brewer.pal(11, "Spectral")), space="Lab")
# Plot
ggplot(df, aes(x,y, fill=..level..) ) +
stat_density_2d( bins=11, geom = "polygon") +
scale_fill_gradientn(colours = myPalette(11)) +
theme_minimal() +
coord_fixed(ratio = 1)

ggplot2 z clipping: remove unnecessary points in overlapping stacks

Consider the following example of plotting 100 overlapping points:
ggplot(data.frame(x=rnorm(100), y=rnorm(100)), aes(x=x, y=y)) +
geom_point(size=100) +
xlim(-10, 10) +
ylim(-10, 10)
I now want to save the image as vector graphics, e.g. in PDF. This is not a problem with the above example, but once I've got over a million points (e.g. from a volcano plot), the file size can exceed 100 MB for one page and it takes ages to display or edit.
In the above example the same shape could could still be represented by either
converting the points to a shape outline, or
keeping a couple of points and discarding the rest.
Is there any way (or preferably tool that already does this) to remove points from a plot that will never be visible? (ideally supporting transparency)
The best approach I have heard so far is to round the position of the dots and remove grid points that have > N points, then use the original positions of the remaining ones. Is there anything better?
Note that this should work with an arbitrary structure of points, and only remove those that are not visible.
You could do something with the convex hull, like this, filling in the polygon that makes up the convex hull:
library(ggplot2)
set.seed(123)
df <- data.frame(x = rnorm(100), y = rnorm(100))
idx <- chull(df)
ggplot(df, aes(x = x, y = y)) +
geom_point(size = 100,color="darkgrey") +
geom_polygon(data=df[idx,],color="blue") +
geom_point(size = 1, color = "red", size = 2) +
xlim(-10, 10) +
ylim(-10, 10)
yielding:
(Note that I pulled this chull-idea out of Hadley's "Extending ggplot2" guide https://cran.r-project.org/web/packages/ggplot2/vignettes/extending-ggplot2.html.)
In your case you would drop the geom_point calls and set transparency on the geom_polygon. Also not sure how fast chull is for millions of points, though it will clearly be faster than plotting them all.
And I am not really sure what you are after. If you really want the 100 pixel radius, they you could probably just do it for the ones on the complex hull, plus fill in the middle with geom_polygon.
So using this code:
ggplot(df[idx,], aes(x = x, y = y)) +
geom_point(size = 100, color = "black") +
geom_polygon(fill = "black") +
xlim(-10, 10) +
ylim(-10, 10)
to make this:

Coordinate points appropriately sized in ggplot2

I have sampled 10,000 coordinates from my data in this file. I have around 130,000 points.
https://www.dropbox.com/s/40hfyx6a5hsjuv7/data.csv
I am trying to plot these points on the Americas map using ggplot2. Here is my code.
library(ggplot2)
library(maps)
map_world <- map_data("world")
map_world <- subset(map_world, (lat >= -60 & lat <= 75))
map_world <- subset(map_world, (long >= -170 & long <= -30))
p <- ggplot(data = data_coords, legend = FALSE) +
geom_polygon(data = map_world, aes(x = long, y = lat, group = group)) +
geom_point(aes(x = lon, y = lat), shape = 19, size = 0.00001,
alpha = 0.3, colour = "red") +
theme(panel.grid.major = element_blank()) +
theme(panel.grid.minor = element_blank()) +
theme(axis.text.x = element_blank(),axis.text.y = element_blank()) +
theme(axis.ticks = element_blank()) +
xlab("") + ylab("")
png("my_plot.png", width = 8000, height = 7000, res = 1000)
print(p)
dev.off()
The points seem to cover the whole area in which they were plotted. I would like them to be more smaller to better represent a location. You can see that I've set the size to 0.00001. I was just trying to see if it has any effect but it doesn't seem to help after a certain limit. Is this the best that is possible at this resolution or could it be reduced more?
I had actually plotted around 400,000 points but only on the US map before and they looked much better like below. Hoping to get something like this. Thanks.
https://www.dropbox.com/s/8d0niu9g6ygz0wo/Clusters_reduced.png
Try playing with very small values of alpha, instead of the point size:
http://docs.ggplot2.org/0.9.3.1/geom_point.html
# Varying alpha is useful for large datasets
d <- ggplot(diamonds, aes(carat, price))
d + geom_point(alpha = 1/1000)
Edit:
Additional ideas are given in the documentation. Here's a summary:
Details
The scatterplot is useful for displaying the relationship between two continuous variables, although it can also be used with one continuous and one categorical variable, or two categorical variables. See geom_jitter for possibilities.
The bubblechart is a scatterplot with a third variable mapped to the size of points. There are no special names for scatterplots where another variable is mapped to point shape or colour, however.
The biggest potential problem with a scatterplot is overplotting: whenever you have more than a few points, points may be plotted on top of one another. This can severely distort the visual appearance of the plot. There is no one solution to this problem, but there are some techniques that can help. You can add additional information with stat_smooth, stat_quantile or stat_density2d. If you have few unique x values, geom_boxplot may also be useful. Alternatively, you can summarise the number of points at each location and display that in some way, using stat_sum.
Another technique is to use transparent points, geom_point(alpha = 0.05).
Edit 2:
Combining the details from the manual with the hints in Transparency and Alpha levels for ggplot2 stat_density2d with maps and layers in R
This might look like the solution:
library(ggplot2)
library(maps)
data_coords <- read.csv("C:/Downloads/data.csv")
map_world <- map_data("world")
map_world <- subset(map_world, (lat >= -60 & lat <= 75))
map_world <- subset(map_world, (long >= -170 & long <= -30))
p <- ggplot( data = data_coords, legend = FALSE) +
geom_polygon( data = map_world, aes(x = long, y = lat, group = group)) +
stat_density2d( data = data_coords, aes(x=lon, y=lat, fill = as.factor(..level..)), size=1, bins=10, geom='polygon') +
scale_fill_manual(values = c("yellow","red","green","royalblue", "black","white","orange","brown","grey"))
png("my_plot2k.png", width = 2000, height = 2000, res = 500)
print(p)
dev.off()
Resulting image (not the best colour palette used):

Resources