I'm having an issue with finding answers for a fairly simple question. I just need to move the axis titles (xlab and ylab) away from the axes. I haven't uploaded reproducible data since the files are large shapefiles, but I can upload it if needed (I figure it's a fairly straightforward answer). I have attached the code I've used so far as well as the map I'm struggling with:
LandUseMap <- tm_shape(LandUseshape, ylim = c(50.45, 50.68), xlim=c(-105,
-104.7), projection = "longlat") +
tm_fill("COVTYPE", title = "Land Cover Type",style="fixed",breaks=c(20,30,34,50,110,121,122,220,230),
labels=c("Water","Non-Vegetated Land","Developed","Shrubland","Grassland","Annual Cropland","Perennial Crops/Pasture","Broadleaf","No Data"),
palette=manualpal) +
tm_borders("grey") +
tm_legend(outside = TRUE, text.size = .65) +
tm_layout(frame = FALSE,asp =NA, outer.margins = c(0.05,0.1,0,0), inner.margins = c(0.05,0.05,0.01,0.05))+
tm_grid(y=c(50.45, 50.50, 50.55, 50.60, 50.65), x=c(-105.0,-104.9,-104.8,-104.7),labels.inside.frame = FALSE, col = "#00ff0000",
labels.size =0.8)+
tm_xlab("Longitude", size = 1)+
tm_ylab("Latitude", size = 1)+
tm_scale_bar(size = 1, position = c(0,0.8)) +
tm_compass(size=2.5,north = 0,position = c(0,0.9))
LandUseMap
Here's the map:
Related
I am trying to make my beautiful ggplot map interactive with a tooltip using ggplotly. But the map rendered with ggploty is not beautiful.
Here is a picture of my map with only ggplot:
Here is a picture of my map when using ggplotly. It removes the legend and make the map ugly:
Is there another way of making my ggplot map interactive with a tooltip? And also ggplotly takes some time to render the interactive map:
Here is my sample code for my ggplot:
ggplot(data = sdpf_f, aes( fill = n,x = long, y = lat, group = group, text = tooltip)) +
geom_polygon(color = "white") +
theme_void() +
scale_fill_continuous(low="#c3ffff", high="#0291da",
guide = guide_legend(title.position = "top", label.position = "bottom", keywidth = 2,
keyheight = 0.5,
title = "Number of agreements"),na.value="lightgrey"
) +
theme(legend.position="bottom") +
coord_map()
Thanks & kind regards,
Akshay
I don't have your data and this isn't exactly the same, but it's fairly close to what I think you're expecting.
The libraries:
I called tidyverse for the plotting and piping. I called maps for the data I used and plotly for the Plotly graph.
I used a function that is derived from one of the ways ggplot sets the aspect ratio. I know I found this function on SO, but I don't remember who wrote it.
library(tidyverse)
library(maps)
library(plotly)
map_aspect = function(x, y) {
x.center <- sum(range(x)) / 2
y.center <- sum(range(y)) / 2
x.dist <- ggplot2:::dist_central_angle(x.center + c(-0.5, 0.5), rep(y.center, 2))
y.dist <- ggplot2:::dist_central_angle(rep(x.center, 2), y.center + c(-0.5, 0.5))
y.dist / x.dist
}
I had to create data as your question is not reproducible. I figured I would include it, so that my answer was reproducible.
ms <- map_data("state") %>%
mutate(n = ifelse(str_detect(region, "^a"), 1.0,
ifelse(str_detect(region, "^o"), 1.5,
ifelse(str_detect(region, "^t"), 2.0,
ifelse(str_detect(region, "^s"), 2.5,
ifelse(str_detect(region, "^w"),
3.0,
NA))))))
I modified your ggplot call. The only change is coord_fixed instead of coord_map. I did this so that Plotly could interpret the aspect ratio correctly. Within coord_fixed, I used the function map_aspect.
gp <- ggplot(data = ms, aes(fill = n, x = long, y = lat,
group = group, text = tooltip)) +
geom_polygon(color = "white") +
theme_void() +
scale_fill_continuous(low="#c3ffff", high="#0291da",
guide = guide_legend(title.position = "top",
label.position = "bottom",
keywidth = 2,
keyheight = 0.5,
title = "Number of agreements"),
na.value="lightgrey"
) +
theme(legend.position="bottom") +
coord_fixed(with(ms, map_aspect(long, lat)))
Then I created a Plotly object. I set some requirements for the layout, as well (horizontal legend at the bottom, with the legend title above the elements—similar to the legend in your ggplot call).
pp <- ggplotly(gp) %>%
layout(legend = list(orientation = "h", valign = "bottom",
title = list(side = "top"),
x = .02),
xaxis = list(showgrid = F), yaxis = list(showgrid = F),
showlegend = T)
Next, I needed to add the information for the legend. I chose to name the traces (which are split by color). I started by creating a vector of the names of the traces (which is what you see in the legend). I added a "" at the end, so that the NA-colored states wouldn't have a named trace (so they won't show in the legend).
This is likely something you'll need to change for your data.**
# the color values and the last one, which is for NAs, no legend
nm <- seq(1, 3, by = .5) %>% sprintf(fmt = "%.1f") %>% append(., "")
Then I wanted to ensure that showlegend was true for all but the NA (light gray) states. I created a vector of T and F.
legs <- c(rep(TRUE, 5), FALSE)
Then I added these to the plot.
invisible(lapply(1:length(pp$x$data),
function(i){
pp$x$data[[i]]$name <<- nm[i]
pp$x$data[[i]]$showlegend <<- legs[i]
}))
I'm trying to plot two plots side by side. One is a RasterStack for which I'm using plotRGB(). The axes are a mess however - it is plotting too many decimal places for the latitude and longitude. I'd also like to change the font size and text orientation.
This is straightforward in plot(), but I can't figure it out for plotRGB.
Can anyone help?
This is the code:
par(mar=c(4,5,4,2), mfrow = c(1, 2))
plotRGB(tayRGB, axes = TRUE, stretch = "lin", main = "RGB")
plot(knr, main = "Kmeans", cex.axis=0.96, col = viridis_pal(option="D")(10))
Can I recommend to use the function RStoolbox)::ggRGB instead of plotRGB. This will give you the full functionality of ggplot to customise your plot. A reproducible example:
set.seed(123)
R = raster(matrix(runif(400),20,20))
G = raster(matrix(runif(400),20,20))
B = raster(matrix(runif(400),20,20))
tayRGB = brick(list(R,G,B))
library(RStoolbox)
p1 = ggRGB(tayRGB, r=1, g=2, b=3, stretch = 'lin') +
scale_y_continuous(labels = scales::number_format(accuracy = 0.001)) +
scale_x_continuous(labels = scales::number_format(accuracy = 0.1)) +
theme(axis.title.x = element_text(size = 30),
axis.text.y = element_text(angle = 45))
p1
To plot your other plot side by side with this, you can either remake it as a ggplot. Or you can use ggplotify::base2grob to convert a base R plot into a grob.
p2 = ggplotify::base2grob(~plot(rnorm(100)))
cowplot::plot_grid(p1,p2)
I made the following graph using the geomnet package and ggplot2. Then exported it to a pdf. But the graph by itself seems to be larger than the graphing area. it seems to be framed in a small square, as you can see in this picture:
graph
I don't know how to change the size of the square that's framing my graph so that the net nodes will be shown fully in my pdf. Thanks in advance.
Here's the code i'm using, and a data example:
red_list<-data_frame(From=c("A","B","C","D","D"),To=c("C","C","D","Z","A"))
red_list%>%ggplot(aes(from_id=From,to_id=To))+
geom_net(layout.alg = "circle", labelon = TRUE,
size = 12, directed = TRUE, fontsize=2, vjust = 0.5, labelcolour = "grey80",
arrowsize = 1.5, linewidth = 0.5, arrowgap = 0.05, col="darkred",
selfloops = F, ecolour = "grey40") +
theme_net() +
theme(plot.title=element_text(hjust=.5),
plot.subtitle=element_text(hjust=.5))+
ggtitle(label=paste("Figura",i,sep=" "),subtitle = paste("Interacciones entre los sectores de",names(red_list)[i],by=" ")))
I'm not sure how well it will work with graphs, but I uselly play with coord_cartesian(xlim = c(...,...), ylim = c(...,...) to adjust the plotting area.
I have this code:
tm_shape(usa, bbox = bbox, projection = map.crs)+
tm_borders(col = "grey", lwd = 1) +
tm_fill(palette = "grey") +
tm_grid(x = c(-77,-75,-73,-71),
y = c(39,37,35),
labels.inside.frame = F,
labels.size = 1.1,
col = "white") +
tm_layout(outer.margins = c(.1,.03,.05,.05),
outer.bg.color = "white")+
tm_shape(sk.dat1,axes = T) +
tm_dots("DATELAND", palette = colo,
auto.palette.mapping=FALSE,
size = .5,
breaks = seq(2010,2017,
length.out =8),legend.show = T, alpha=.7) +
tm_layout(title = "Southern Kingfish Occurrence",
legend.show = T,
legend.position = c("right","bottom"),
legend.bg.color = "grey70",
legend.height = 2)
Which outputs this legend. How can I change the tmap input to only include single years with no commas?
This looks as a number format problem; your code is not exactly reproducible, so I can not make 100% sure, but I am fairly certain by the look.
To remedy try including this in your tm_layout call:
legend.format=list(fun=function(x) formatC(x, digits=0, format="d"))
By the way I wrote a short blog post on tmap legend formatting a couple months back (my problem were currency and percentage signs).
https://www.jla-data.net/eng/tmap-legend/
My map-making code generates a map based on census data and plots important points as a tm_dots() layer. What I'd like to be able to do is differentiate between the types of dots (e.g. if the location is "Informal" or "Commercial").
tm_shape(bristol) + tm_fill("population", palette = "YlOrRd",
auto.palette.mapping = TRUE,
title = "Bristol Population",
breaks = c(0,5,10,15,20,25), colorNA = "darkgrey") + tm_borders("grey25",alpha = 0.7, lwd = 0.1) +
tm_dots("n", size=0.1,col="green", shapeNA = NA, title = "Spaces") +
tm_legend(text.size=1,title.size=1.2,position=c("left","top")) +
tm_layout(legend.outside = TRUE, legend.outside.position = "bottom", title.snap.to.legend = TRUE)
What I'm looking for is essentially:
tm_dots("n", size=0.1,col=Classification, shapeNA = NA, title = "Spaces")
Adding several tm_dots() layers isn't an option. I also can't rename the dot legend, any advice on that too is appreciated.
Thanks for your help!
Solution
For future reference, I added offices to bristol via left_join, thus adding the Classification variable to the SpatialPolygonsDataFrame. I was having issues with it displaying NA values despite the showNA = NA parameter, but colorNA = NULL worked. Final line:
tm_dots(size=0.1,col="Classification", palette = "Set1", colorNA = NULL)
So bristol is a polygon shape (SpatialPolygonDataFrame or sf), and you want to plot dots in some polygons?
Normally, you would have a variable Offices, with two levels "Informal" and "Commercial". Then it's just tm_dots(size = 0.1, col = "Offices"). If you want to place two dots in one polygons because there are Informal and Commercial offices, then you can use your own approach (and use xmod and/or ymod for one group to prevent overlap), or create a SpatialPointsDataFrame or sf object with all offices, and a variable Offices with two levels as described above.
I figured it out, you need to have another tm_shape() for it to work. Still haven't got the title() to appear properly but one step at a time.
tm_shape(bristol) + tm_fill("population", palette = "YlOrRd", auto.palette.mapping = TRUE,
title = "Bristol Population",
breaks = c(0,5,10,15,20,25), colorNA = "darkgrey") + tm_borders("grey25",alpha = 0.7, lwd = 0.1) +
tm_dots("Informal_Offices", size=0.1,col="green", shapeNA = NA, title = "Informal Offices") +
tm_shape(bristol) + tm_dots("Commercial_Offices", size=0.1,col="white",shapeNA=NA, title="Commercial Offices") +
tm_legend(text.size=1,title.size=1.2,position=c("left","top")) +
tm_layout(legend.outside = TRUE, legend.outside.position = "bottom", title.snap.to.legend = TRUE)
Result