Latitude Longitude Coordinates to State Code in R
Here are two options, one using sf and one using sp package functions. sf is the more modern (and, here in 2020, recommended) package for analyzing spatial data, but in case it's still useful, I am leaving my original 2012 answer showing how to do this with sp-related functions.
Method 1 (using sf):
library(sf)
library(spData)
## pointsDF: A data.frame whose first column contains longitudes and
## whose second column contains latitudes.
##
## states: An sf MULTIPOLYGON object with 50 states plus DC.
##
## name_col: Name of a column in `states` that supplies the states'
## names.
lonlat_to_state <- function(pointsDF,
states = spData::us_states,
name_col = "NAME") {
## Convert points data.frame to an sf POINTS object
pts <- st_as_sf(pointsDF, coords = 1:2, crs = 4326)
## Transform spatial data to some planar coordinate system
## (e.g. Web Mercator) as required for geometric operations
states <- st_transform(states, crs = 3857)
pts <- st_transform(pts, crs = 3857)
## Find names of state (if any) intersected by each point
state_names <- states[[name_col]]
ii <- as.integer(st_intersects(pts, states))
state_names[ii]
}
## Test the function with points in Wisconsin, Oregon, and France
testPoints <- data.frame(x = c(-90, -120, 0), y = c(44, 44, 44))
lonlat_to_state(testPoints)
## [1] "Wisconsin" "Oregon" NA
If you need higher resolution state boundaries, read in your own vector data as an sf
object using sf::st_read()
or by some other means. One nice option is to install the rnaturalearth package and use it to load a state vector layer from rnaturalearthhires. Then use the lonlat_to_state()
function we just defined as shown here:
library(rnaturalearth)
us_states_ne <- ne_states(country = "United States of America",
returnclass = "sf")
lonlat_to_state(testPoints, states = us_states_ne, name_col = "name")
## [1] "Wisconsin" "Oregon" NA
For very accurate results, you can download a geopackage containing GADM-maintained administrative borders for the United States from this page. Then, load the state boundary data and use them like this:
USA_gadm <- st_read(dsn = "gadm36_USA.gpkg", layer = "gadm36_USA_1")
lonlat_to_state(testPoints, states = USA_gadm, name_col = "NAME_1")
## [1] "Wisconsin" "Oregon" NA
Method 2 (using sp):
Here is a function that takes a data.frame of lat-longs within the lower 48 states, and for each point, returns the state in which it is located.
Most of the function simply prepares the SpatialPoints
and SpatialPolygons
objects needed by the over()
function in the sp
package, which does the real heavy lifting of calculating the 'intersection' of points and polygons:
library(sp)
library(maps)
library(maptools)
# The single argument to this function, pointsDF, is a data.frame in which:
# - column 1 contains the longitude in degrees (negative in the US)
# - column 2 contains the latitude in degrees
lonlat_to_state_sp <- function(pointsDF) {
# Prepare SpatialPolygons object with one SpatialPolygon
# per state (plus DC, minus HI & AK)
states <- map('state', fill=TRUE, col="transparent", plot=FALSE)
IDs <- sapply(strsplit(states$names, ":"), function(x) x[1])
states_sp <- map2SpatialPolygons(states, IDs=IDs,
proj4string=CRS("+proj=longlat +datum=WGS84"))
# Convert pointsDF to a SpatialPoints object
pointsSP <- SpatialPoints(pointsDF,
proj4string=CRS("+proj=longlat +datum=WGS84"))
# Use 'over' to get _indices_ of the Polygons object containing each point
indices <- over(pointsSP, states_sp)
# Return the state names of the Polygons object containing each point
stateNames <- sapply(states_sp@polygons, function(x) x@ID)
stateNames[indices]
}
# Test the function using points in Wisconsin and Oregon.
testPoints <- data.frame(x = c(-90, -120), y = c(44, 44))
lonlat_to_state_sp(testPoints)
[1] "wisconsin" "oregon" # IT WORKS
is there an R code to separate coordinates latitudes and longitudes with differing lengths?
I already answered your updated question in a comment to my original answer, but I can appreciate that it may have been hard to understand as a comment.
First, we'll combine the steps that I laid out earlier into a function parse_line()
.
parse_line <- function(line){
coord_pairs <- strsplit(line, split = ";")
# Separate the latitude-longitude components
coords <- strsplit(unlist(coord_pairs), split = ",") # We have to unlist coord_pairs because strsplit() expects a character vector
# coords is a list of two-element vectors (lat and long)
# Combine the elements of coords into a matrix, then coerce to a dataframe
df <- as.data.frame(do.call(rbind, coords))
}
Then we'll use parse_line()
as a building block for a similar function parse_lines()
.
parse_lines <- function(cluster_ids, lines){
parsed_dfs <- Map(function(x, y) cbind(x, parse_line(y)), cluster_ids, lines)
# Iterates over all the pairs of cluster_ids and lines
# and adds the cluster_id as a column to the dataframe produced by calling
# parse_line() on the corresponding line
combined_df <- do.call(rbind, parsed_dfs) # Combines the list of dataframes into a single dataframe
colnames(combined_df) <- c("Cluster_ID", "Latitude", "Longitude") # Adds appropriate column names
return(combined_df)
}
parse_lines(cluster_ids, lat_long)
How do I automatically determine a state given the latitude and longitude / coordinates?
Use function over
from sp
package:
library(geojsonio)
library(sp)
# get usa polygon data
# http://eric.clst.org/tech/usgeojson/
usa <- geojson_read(
"http://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_040_00_500k.json",
what = "sp"
)
df$state <- NA
# compare points
for (i in 1:nrow(df)) {
coords <- c(df$origin_lon[i], df$origin_lat[i])
if(any(is.na(coords))) next
point <- sp::SpatialPoints(
matrix(
coords,
nrow = 1
)
)
sp::proj4string(point) <- sp::proj4string(usa)
polygon_check <- sp::over(point, usa)
df$state[i] <- as.character(polygon_check$NAME)
}
> head(df)
origin_coords origin_lat origin_lon state
1 31.9618,-83.0588 31.9618 -83.0588 Georgia
2 44.8782,-69.4718 44.8782 -69.4718 Maine
3 37.3894,-121.8868 37.3894 -121.8868 California
4 36.0485,-93.5044 36.0485 -93.5044 Arkansas
5 37.652,-120.7292 37.6520 -120.7292 California
6 33.7942,-84.2018 33.7942 -84.2018 Georgia
Convert latitude and longitude coordinates to country name in R
Thanks for the carefully constructed question.
It required just a couple of line changes to be able to use rworldmap (containing up-to-date countries) see below. I'm not an expert on CRS but I don't think the change I had to make to the proj4string makes any difference. Others might like to comment on that.
This worked for me & gave :
> coords2country(points)
[1] United Kingdom Belgium Germany Austria
[5] Republic of Serbia
All the best,
Andy
library(sp)
library(rworldmap)
# The single argument to this function, points, is a data.frame in which:
# - column 1 contains the longitude in degrees
# - column 2 contains the latitude in degrees
coords2country = function(points)
{
countriesSP <- getMap(resolution='low')
#countriesSP <- getMap(resolution='high') #you could use high res map from rworldxtra if you were concerned about detail
# convert our list of points to a SpatialPoints object
# pointsSP = SpatialPoints(points, proj4string=CRS(" +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0"))
#setting CRS directly to that from rworldmap
pointsSP = SpatialPoints(points, proj4string=CRS(proj4string(countriesSP)))
# use 'over' to get indices of the Polygons object containing each point
indices = over(pointsSP, countriesSP)
# return the ADMIN names of each country
indices$ADMIN
#indices$ISO3 # returns the ISO3 code
#indices$continent # returns the continent (6 continent model)
#indices$REGION # returns the continent (7 continent model)
}
Convert latitude/longitude to state plane coordinates
When you set the coordinates
for your data, you have to set the latitude before the longitude.
In other words, change:
coordinates(data) <- ~ long + lat
to
coordinates(data) <- ~ lat+long
And it should work.
library(rgdal)
library(sp)
data = data.frame(long=c(41.20,40.05), lat=c(-86.14,-88.15))
coordinates(data) <- ~ lat+long
proj4string(data) <- CRS("+init=epsg:4326")
data.proj <- spTransform(data, CRS("+init=epsg:2790"))
data.proj
Gave me this output:
SpatialPoints:
lat long
[1,] 483979.0 505572.6
[2,] 315643.7 375568.0
Coordinate Reference System (CRS) arguments: +init=epsg:2790 +proj=tmerc
+lat_0=36.66666666666666 +lon_0=-88.33333333333333 +k=0.9999749999999999 +x_0=300000
+y_0=0 +ellps=GRS80 +units=m +no_defs
Getting Latitude and Longitude in R with only city, state
If you'd like to go ahead and add state abbreviation, this should work for you:
df <- DF %>%
geocode(city = Cities, state = st, method = "census")
Related Topics
How Does One Reorder Columns in a Data Frame
Group by Multiple Columns in Dplyr, Using String Vector Input
Select First and Last Row from Grouped Data
Method to Extract Stat_Smooth Line Fit
How to Extract a Single Column from a Data.Frame as a Data.Frame
Painless Way to Install a New Version of R
How to Remove All Whitespace from a String
Incomplete Final Line' Warning When Trying to Read a .Csv File into R
How to Use Grep()/Gsub() to Find Exact Match
Why Do R Objects Not Print in a Function or a "For" Loop
Locate the ".Rprofile" File Generating Default Options
Rotating X Axis Labels in R For Barplot
Formatting Dates on X Axis in Ggplot2
Figure Position in Markdown When Converting to Pdf With Knitr and Pandoc