2013-01-15 179 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 –