geom_sf: How to get decimal degrees on my longitude and latitude axes

Not sure where to categorize this.

I'm trying to migrate my code to geom_sf et al and find that I am stuck with degrees, minutes, seconds on the axes. I have scoured the Google-verse but no joy.

Is there anyone who can point me in the right direction to come up with a way to get geom_sf to plot in decimal degrees?


Furthermore, the convention that I want to use is decimal degrees and negative longitude values in the western hemisphere and negative latitude values in the southern hemisphere.

Is there no way to control this directly? It seems to be implicit wrt the CRS and some hard-wired convention of using WESN indicators for hemisphere. Is this correct?

Read origin of this answer at end before trying
In R, you can convert your coordinates from degrees, minutes, and seconds (DMS) to decimal degrees using the sp package. The convention you want to use, where negative longitude values are in the western hemisphere and negative latitude values are in the southern hemisphere, is the standard in geographic coordinate systems[5].

Here's a simple function to convert DMS to decimal degrees:

dms_to_decimal <- function(degrees, minutes, seconds, hemisphere) {
  decimal <- degrees + minutes / 60 + seconds / 3600
  if (hemisphere %in% c('S', 'W')) {
    decimal <- -decimal

You can apply this function to your data frame columns accordingly. For example, if you have a data frame df with columns Lat_Deg, Lat_Min, Lat_Sec, Lat_Hem, Long_Deg, Long_Min, Long_Sec, Long_Hem, you can create new columns Lat and Long in decimal degrees as follows:

df$Lat <- with(df, mapply(dms_to_decimal, Lat_Deg, Lat_Min, Lat_Sec, Lat_Hem))
df$Long <- with(df, mapply(dms_to_decimal, Long_Deg, Long_Min, Long_Sec, Long_Hem))

Once you have your coordinates in decimal degrees, you can use geom_sf in ggplot2 to plot your data. The geom_sf function automatically handles the projection of your data, so you don't need to worry about converting your coordinates to a different system[3].

Remember to ensure that your data is in the correct format before plotting. For instance, the sf package in R allows you to create spatial objects from data frames, which can then be used with geom_sf [3]. If your data is not already in this format, you can use the st_as_sf function from the sf package to convert it[3].

[1] r - Converting latitude and longitude - Stack Overflow
[2] Standard Latitudes and Longitudes | R-bloggers
[3] Introduction to geospatial data analysis in R
[4] r - Converting DMS to coordinates with +/- signs - Geographic Information Systems Stack Exchange
[5] Chapter 2 Spatial data in R | Spatial Statistics for Data Science: Theory and Practice with R

Comment: This is from a bot. It looks reasonable, but I haven't tested.

Well, it's not correct. That's not what happens.

My bad. I’ll tinker with it. {sf} is the annointed successor to {sp}, so if it’s possible in the later, it should also be in the former.

I'd assume it's something that GIS-people would solve through coord_sf(datum = ...) and appropriate proj-string, but you can try with scale_*_continuous() and scales::label_number():


p1 <- read_sf(system.file("shape/nc.shp", package="sf")) |>
  ggplot() +

p2 <- p1 +
  scale_x_continuous(labels = scales::label_number(accuracy = 0.01)) +
  scale_y_continuous(labels = scales::label_number(accuracy = 0.01))

patchwork::wrap_plots(p1 + ggtitle("NAD27 datum"), 
                      p2 + ggtitle("scales::label_number()"), 
                      nrow = 2)

Created on 2023-11-15 with reprex v2.0.2

This is pretty basic stuff in earth science. When the data (lon, lat) are in signed coordinate values, you want to see them plotted in those units. Insisting that WESN be used interferes with interpreting the data; therefore, very bad idea.

I'm able to kluge it using scale_(x,y)_continuous to get decimal values but haven't found a way to get the sign to be part of the label.

scales_label_number() looks promising.

That works. Mahalo for your manao.

I would suggest, to whoever maintains scales, that the argument should be precision=0.01 rather than accuracy.

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.