R从网格化数据中提取点的类别

时间:2016-09-15 23:56:49

标签: r mapping matching

我有一个位置数据框,我一直想把它们与地图中的分类变量(气候区域)相匹配。这是一个小摘录:

df <- data.frame(lat = c(29.30050,  47.67309,  53.30710, -27.60303,  41.31858,  40.50738,  
                         50.67013,60.23163,  42.54555), 
                 long = c(47.806320, -122.315312,   -6.281798,  151.951778,  -72.849961,  
                          -74.382711, 4.348718, 19.710874,  -71.038764))

我了解了从excellent article获取数据的位置。我想要做的是为我的数据框中的每个点集提取分类变量。这可能听起来微不足道,但我是绘图新手并且找不到任何帮助文章。问题可能是我使用了错误的条款!

使用本教程映射数据集非常简单,但网格匹配超出了我的范围。分类地图数据以.txt,.kmz或GIS格式here提供,因此我不限于一种方法。

我已经尝试了每个lat和long的最近匹配,但它无法区分网格的哪一侧可供选择。我已经挖掘了关于pastor,rworldmap,rgdal以及我在堆栈溢出时可以找到的所有搜索组合的文档。

1 个答案:

答案 0 :(得分:3)

如果我们从网站下载数据并将其作为koeppen读取,例如

download.file('http://koeppen-geiger.vu-wien.ac.at/data/Koeppen-Geiger-ASCII.zip', 
              'Koeppen-Geiger-ASCII.zip', 
              method = 'curl')

# use read.table if you like, but read_table cuts a lot of hassle with poor formatting
koeppen <- readr::read_table('Koeppen-Geiger-ASCII.zip')

我们会查看数据,所有纬度和经度都不方便地以.25.75结束:

koeppen
## # A tibble: 92,416 × 3
##       Lat     Lon   Cls
##     <dbl>   <dbl> <chr>
## 1  -89.75 -179.75    EF
## 2  -89.75 -179.25    EF
## 3  -89.75 -178.75    EF
## 4  -89.75 -178.25    EF
## 5  -89.75 -177.75    EF
## 6  -89.75 -177.25    EF
## 7  -89.75 -176.75    EF
## 8  -89.75 -176.25    EF
## 9  -89.75 -175.75    EF
## 10 -89.75 -175.25    EF
## # ... with 92,406 more rows

因此,要合并这两个表,我们需要将df的纬度和经度舍入到.25.75,例如由

df[] <- lapply(df, function(x){ifelse(x %% 1 > .5, 0.75, 0.25) + floor(x)})

得到余数除以1,即非整数部分,如果它大于.5则返回.75,否则返回.25,然后重新添加整数部分,所以df现在看起来像:

df
##      lat    long
## 1  29.25   47.75
## 2  47.75 -122.25
## 3  53.25   -6.25
## 4 -27.75  151.75
## 5  41.25  -72.75
## 6  40.75  -74.25
## 7  50.75    4.25
## 8  60.25   19.75
## 9  42.75  -71.25 

现在我们可以使用merge(或dplyr连接,如果您愿意)将Cls列添加到df以匹配纬度和经度:

df <- merge(df, koeppen, 
            by.x = c('lat', 'long'), 
            by.y = c('Lat', 'Lon'), 
            all.x = TRUE)

# or dplyr::left_join(df, koeppen, by = c('lat' = 'Lat', 'long' = 'Lon'))

df
##      lat    long Cls
## 1 -27.75  151.75 Cfa
## 2  29.25   47.75 BWh
## 3  40.75  -74.25 Cfa
## 4  41.25  -72.75 Cfa
## 5  42.75  -71.25 Dfb
## 6  47.75 -122.25 Csb
## 7  50.75    4.25 Cfb
## 8  53.25   -6.25 Cfb
## 9  60.25   19.75 Dfb

如果您喜欢语法,这对data.table's non-equi-joins也可能是个好例子。