在GeoJSON和sf之间转换

在GeoJSON和sf之间转换

本文是学习Converting between GeoJSON and sfSymbolixAU/geojsonsf的笔记,介绍了如何使用geojsonsf包进行GeoJSON和sf两种格式的转换。

安装

R
1
install.packages("geojsonsf")

功能

  • GeoJSON –> sf
  • GeoJSON –> sfc
  • sf –> GeoJSON
  • sfc –> GeoJSON
  • GeoJSON –> Well-known text
  • data.frame –> GeoJSON (POINT only)

GeoJSON -> sf

R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
library(geojsonsf)
json <- c(
'[
{"type":"Point","coordinates":[0,0]},
{"type":"LineString","coordinates":[[-1,-1],[1,1]]},
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"id":1},
"geometry": {"type": "Point", "coordinates": [100.0, 0.0]}
}
]
}
]'
)
(sf <- geojson_sf(json))

结果:

R
1
2
3
4
5
6
7
8
9
10
Simple feature collection with 3 features and 1 field
geometry type: GEOMETRY
dimension: XY
bbox: xmin: -1 ymin: -1 xmax: 100 ymax: 1
epsg (SRID): 4326
proj4string: +proj=longlat +datum=WGS84 +no_defs
id geometry
1 NA POINT (0 0)
2 NA LINESTRING (-1 -1, 1 1)
3 1 POINT (100 0)

sf -> GeoJSON

R
1
2
3
4
(json <- sf_geojson(sf))

# 结果
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"id":null},"geometry":{"type":"Point","coordinates":[0.0,0.0]}},{"type":"Feature","properties":{"id":null},"geometry":{"type":"LineString","coordinates":[[-1.0,-1.0],[1.0,1.0]]}},{"type":"Feature","properties":{"id":1.0},"geometry":{"type":"Point","coordinates":[100.0,0.0]}}]}

另外可以使用atomise参数使返回的结果分离成单独的记录:

R
1
2
3
4
5
6
(json <- sf_geojson(sf, atomise = T))

# 结果
{"type":"Feature","properties":{"id":null},"geometry":{"type":"Point","coordinates":[0.0,0.0]}}
{"type":"Feature","properties":{"id":null},"geometry":{"type":"LineString","coordinates":[[-1.0,-1.0],[1.0,1.0]]}}
{"type":"Feature","properties":{"id":1.0},"geometry":{"type":"Point","coordinates":[100.0,0.0]}}

也可以只返回几何形状:

R
1
2
3
4
5
6
(json <- sfc_geojson(sf$geometry))

# 结果
{"type":"Point","coordinates":[0.0,0.0]}
{"type":"LineString","coordinates":[[-1.0,-1.0],[1.0,1.0]]}
{"type":"Point","coordinates":[100.0,0.0]}

你会发现返回的结果是直接将记录分离。

比较两种生成sf的方法的速度

下载文件:gz_2010_us_050_00_500k.json

R
1
2
3
4
5
6
7
8
9
10
11
12
13
geo <- readLines("gz_2010_us_050_00_500k.json")
geo <- paste0(geo, collapse = "")

library(microbenchmark)
microbenchmark(
geojson_sf = {
geojson_sf(geo)
},
sf = {
sf::st_read(geo, quiet = T)
},
times = 5
)

结果:

R
1
2
3
4
Unit: milliseconds
expr min lq mean median uq max neval
geojson_sf 857.7921 897.6367 953.2462 920.2638 935.3781 1155.160 5
sf 2868.0864 2991.8972 3139.6887 3137.4531 3193.0357 3507.971 5

5次对比的结果表明,geojson_sf()效率更高。

绘图

R
1
2
sf <- sf::read_sf(geo)
plot(sf::st_geometry(sf[!sf$STATE %in% c("02", "15", "72"), ]))

R
1
2
gsf <- geojson_sf(geo)
plot(sf::st_geometry(gsf[!gsf$STATE %in% c("02", "15", "72"), ]))

似乎是直接被填充了,自己还不会用sf包,等学了再研究研究吧。

还可以用于ggplot2的绘图

R
1
2
3
library(sf)
ggplot(data = sf) +
geom_sf()

只绘制美国主体:

R
1
2
ggplot(data = sf[!sf$STATE %in% c("02", "15", "72"), ]) +
geom_sf()

我又找了幅中国地图,geojson文件可以在这个仓库里下载:ufoe/d3js-geojson

R
1
2
3
4
download.file("https://github.com/ufoe/d3js-geojson/raw/master/china/china.json", "china.json")
cn <- geojson_sf(readLines("china.json") %>% paste0(collapse = ""))
ggplot(data = cn) +
geom_sf()

再例如绘制我老家阜阳的地图:

R
1
2
3
4
download.file("https://github.com/ufoe/d3js-geojson/raw/master/china/geometryCouties/341200.json", "341200.json")
fy <- geojson_sf(readLines("341200.json") %>% paste0(collapse = ""))
ggplot(data = fy) +
geom_sf()

还可以生成一些随机数据:

R
1
2
3
4
5
6
7
8
9
10
11
df <- data.frame(
name = fy$name,
value = as.integer(runif(8, 5, 20))
)

fy <- merge(fy, df, id = "name")
ggplot(data = fy) +
geom_sf(aes(fill = value)) +
scale_fill_viridis_c() +
theme(panel.background = element_rect(fill = "aliceblue")) +
labs(title = "阜阳地图")

# R

评论

程振兴

程振兴 @czxa.top
截止今天,我已经在本博客上写了659.4k个字了!

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×