2013-01-15 97 views
13

我有纬度和经度坐标的列表,并希望找出他们都居住在哪个国家。转换纬度和经度坐标,以国名中的R

我修改的答案从this question about lat-long to US states,并有一个工作功能,但我遇到的问题是worldHires地图(来自mapdata包)显得过时了,并且包含许多过时的国家,例如南斯拉夫和苏联。

我该如何修改此功能以使用更现代的软件包,例如rworldmap?我只设法阻挠自己那么远,

library(sp) 
library(maps) 
library(rgeos) 
library(maptools) 

# 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) 
{ 
    # prepare a SpatialPolygons object with one poly per country 
    countries = map('worldHires', fill=TRUE, col="transparent", plot=FALSE) 
    names = sapply(strsplit(countries$names, ":"), function(x) x[1]) 

    # clean up polygons that are out of bounds 
    filter = countries$x < -180 & !is.na(countries$x) 
    countries$x[filter] = -180 

    filter = countries$x > 180 & !is.na(countries$x) 
    countries$x[filter] = 180 

    countriesSP = map2SpatialPolygons(countries, IDs=ids, proj4string=CRS("+proj=longlat +datum=wgs84")) 


    # convert our list of points to a SpatialPoints object 
    pointsSP = SpatialPoints(points, proj4string=CRS("+proj=longlat +datum=wgs84")) 


    # use 'over' to get indices of the Polygons object containing each point 
    indices = over(pointsSP, countriesSP) 


    # Return the state names of the Polygons object containing each point 
    myNames = sapply([email protected], function(x) [email protected]) 
    myNames[indices] 
} 

## 
## this works... but it has obsolete countries in it 
## 

# set up some points to test 
points = data.frame(lon=c(0, 5, 10, 15, 20), lat=c(51.5, 50, 48.5, 47, 44.5)) 

# plot them on a map 
map("worldHires", xlim=c(-10, 30), ylim=c(30, 60)) 
points(points$lon, points$lat, col="red") 

# get a list of country names 
coords2country(points) 
# returns [1] "UK"   "Belgium" "Germany" "Austria" "Yugoslavia" 
# number 5 should probably be in Serbia... 
+0

的地图包现在有新的国家进行更新。没有更多的苏联或南斯拉夫等 – ZacharyST

回答

17

感谢精心构建的问题。 它只需要几行更改即可使用rworldmap(包含最新的国家/地区),如下所示。我不是CRS方面的专家,但我不认为我必须对proj4string所做的更改会产生任何影响。其他人可能会对此发表评论。

这为我工作&给:

> coords2country(points) 
[1] United Kingdom  Belgium   Germany   Austria   
[5] Republic of Serbia 

一切顺利, 安迪

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) 
} 
+1

当我尝试使用这个函数时,我得到'identicalCRS(x,y)不是TRUE' –

+0

这应该通过这个编辑来解决:pointsSP = SpatialPoints(points,proj4string = CRS(proj4string(countriesSP))) – Andy

+0

@Andy可以修改它来提取一个大陆吗?当我跑这个时,我也拿到了一些NA。 (53.225516,-4.132845,NA)(41.524314,-70.669578,NA) - 你知道为什么吗? – Ell

8

你可以用我geonames包从http://geonames.org/服务来查找:

> GNcountryCode(51.5,0) 
$languages 
[1] "en-GB,cy-GB,gd" 

$distance 
[1] "0" 

$countryName 
[1] "United Kingdom of Great Britain and Northern Ireland" 

$countryCode 
[1] "GB" 

> GNcountryCode(44.5,20) 
$languages 
[1] "sr,hu,bs,rom" 

$distance 
[1] "0" 

$countryName 
[1] "Serbia" 

$countryCode 
[1] "RS" 

从R锻造得到它,因为我不是相信我不屑于它发布到CRAN:

https://r-forge.r-project.org/projects/geonames/

是的,这取决于外部服务,但至少知道什么Happe的ned to communism ... :)

+0

它似乎API需要在每次调用内置的用户名,但'GNcountryCode'函数不允许用户名。你会调整API调用吗? @Spacedman –