2

I have the following code

ggplot(data=earthquake,aes(longitude,latitude))+
  geom_point(data=earthquake,aes(longitude,latitude),alpha=0.5,col="red",fill="red",shape=21)+
  coord_map(projection = "mollweide",xlim=c(-180,180))+
  xlab("Galactic Longitude")+
  ylab("Galactic Latitude")+
  scale_x_continuous(breaks=seq(-180,180,60),limits=c(-180,180))+
  scale_y_continuous(breaks=seq(-90,90,30))

where earthquake is a matrix of columns "longitude" and "latitude" between -180 and 180, and -90 and 90, respectively. It produces the following plot and clearly the x-axis ticks aren't spaced as they should be.

I would ideally like to recreate this plot in ggplot2 with nicely spaced ticks, and hopefully the ablines of longitude/latitude.

1
  • 2
    I don't think you can put the axis inside the plot without turning to other packages, but the ggh4x package might let you do it as here. Or you could remove the x-axis and plot a line and label it with geom_text(). Commented Jun 26, 2025 at 19:42

1 Answer 1

6

One option could be to manually create the longitude / latitude labels with geom_text with coord_sf(crs = moll_crs, default_crs = st_crs(4326), datum = NA) at the end as pointed out by @IO. You can use hjust / vjust to change the label alignments as per this and size to controll the text size. out

library(sf)
library(ggplot2)

moll_crs <- "+proj=moll +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs"

earthquake_sf <- st_as_sf(geostats::earthquakes, coords = c("lon", "lat"), crs = 4326) |>
  st_transform(crs = moll_crs)

graticule <- st_graticule(lat = seq(-90, 90, 30), lon = seq(-180, 180, 60), crs = 4326) |>
  st_transform(moll_crs)

ggplot() +
  geom_sf(data = graticule, color = "black", size = 0.3, alpha = 0.7) +
  geom_sf(data = earthquake_sf, color = "black", alpha = 0.5, size = 1) +
  # place latitude labels 
  geom_text(aes(x = -180, y = seq(-60, 60, 30), 
                label = paste0(seq(-60, 60, 30), "°")), 
            size = 5, hjust = 1.5) +
  # place longitude labels
  geom_text(aes(x = seq(-120, 120, 60), y = 0,  
                label = paste0(seq(-120, 120, 60), "°")), 
            size = 5, vjust = 1.5, hjust = 1) +
  # place 90 on top / below
  geom_text(aes(x = -180, y = 90, label = "90°"), 
            size = 5, vjust = -0.5) +
  geom_text(aes(x = -180, y = -90, label = "-90°"), 
            size = 5, vjust = 1.5) +
  coord_sf(crs = moll_crs, default_crs = st_crs(4326), datum = NA) +
  theme_minimal() + 
  labs(x = expression(alpha[2000])) +
  theme(axis.title.y = element_blank(), axis.title.x=element_text(size=20))

Note: coord_sf() is designed specifically to work with geom_sf() and spatial data that's already in a proper coordinate reference system (CRS). When you try to use coord_sf() with regular geoms like geom_point() you run the risk of causing several problems like difficult to place gratitude labels.

Sign up to request clarification or add additional context in comments.

2 Comments

It might be useful to be more up-front with the fact that coord_sf() does not work well with non-sf geom_*. It may be obvious to many, but it may not be intuitive to everybody.
Hint: using ... + coord_sf(default_crs = st_crs(4326), datum = NA, ...) allows to (1) use vanilla geom_text (with aesthetics x and y given in degrees) and (2) hide the default graticule.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.