我试图像这样在圣何塞上放置网格:
您可以使用以下代码直观地生成网格:
ca_cities = tigris::places(state = "CA") #using tigris package to get shape file of all CA cities
sj = ca_cities[ca_cities$NAME == "San Jose",] #specifying to San Jose
UTM_ZONE = "10" #the UTM zone for San Jose, will be used to convert the proj4string of sj into UTM
main_sj = sj@polygons[[1]]@Polygons[[5]] #the portion of the shape file I focus on. This is the boundary of san jose
#converting the main_sj polygon into a spatialpolygondataframe using the sp package
tst_ps = sp::Polygons(list(main_sj), 1)
tst_sps = sp::SpatialPolygons(list(tst_ps))
proj4string(tst_sps) = proj4string(sj)
df = data.frame(f = 99.9)
tst_spdf = sp::SpatialPolygonsDataFrame(tst_sps, data = df)
#transforming the proj4string and declaring the finished map as "map"
map = sp::spTransform(tst_sps, CRS(paste0("+proj=utm +zone=",UTM_ZONE," ellps=WGS84")))
#designates the number of horizontal and vertical lines of the grid
NUM_LINES_VERT = 25
NUM_LINES_HORZ = 25
#getting bounding box of map
bbox = map@bbox
#Marking the x and y coordinates for each of the grid lines.
x_spots = seq(bbox[1,1], bbox[1,2], length.out = NUM_LINES_HORZ)
y_spots = seq(bbox[2,1], bbox[2,2], length.out = NUM_LINES_VERT)
#creating the coordinates for the lines. top and bottom connect to each other. left and right connect to each other
top_vert_line_coords = expand.grid(x = x_spots, y = y_spots[1])
bottom_vert_line_coords = expand.grid(x = x_spots, y = y_spots[length(y_spots)])
left_horz_line_coords = expand.grid(x = x_spots[1], y = y_spots)
right_horz_line_coords = expand.grid(x = x_spots[length(x_spots)], y = y_spots)
#creating vertical lines and adding them all to a list
vert_line_list = list()
for(n in 1 : nrow(top_vert_line_coords)){
vert_line_list[[n]] = sp::Line(rbind(top_vert_line_coords[n,], bottom_vert_line_coords[n,]))
}
vert_lines = sp::Lines(vert_line_list, ID = "vert") #creating Lines object of the vertical lines
#creating horizontal lines and adding them all to a list
horz_line_list = list()
for(n in 1 : nrow(top_vert_line_coords)){
horz_line_list[[n]] = sp::Line(rbind(left_horz_line_coords[n,], right_horz_line_coords[n,]))
}
horz_lines = sp::Lines(horz_line_list, ID = "horz") #creating Lines object of the horizontal lines
all_lines = sp::Lines(c(horz_line_list, vert_line_list), ID = 1) #combining horizontal and vertical lines into a single grid format
grid_lines = sp::SpatialLines(list(all_lines)) #converting the lines object into a Spatial Lines object
proj4string(grid_lines) = proj4string(map) #ensuring the projections are the same between the map and the grid lines.
trimmed_grid = intersect(grid_lines, map) #grid that shapes to the san jose map
plot(map) #plotting the map of San Jose
lines(trimmed_grid) #plotting the grid
但是,我正在努力将每个网格“变成正方形”(一些网格块不是正方形,因为它们适合圣何塞地图的形状)到一个可以输入数据的容器中。换句话说,如果每个网格“正方形”的编号为1:n,那么我可以制作一个像这样的数据框:
grid_id num_assaults num_thefts
1 1 100 89
2 2 55 456
3 3 12 1321
4 4 48 498
5 5 66 6
并希望使用over()
软件包中的sp
函数,用数据填充每个网格“正方形”的每次犯罪发生的地点。
我尝试解决此问题已有数周时间,但无法解决。我一直在寻找一个简单的解决方案,但似乎找不到。任何帮助,将不胜感激。
答案 0 :(得分:4)
使用Spatial *对象作为数据
library(tigris)
ca_cities = tigris::places(state = "CA") #using tigris package to get shape file of all CA cities
sj = ca_cities[ca_cities$NAME == "San Jose",] #specifying to San Jose
sjutm = sp::spTransform(sj, CRS("+proj=utm +zone=10 +datum=WGS84"))
您可以像这样制作多边形网格
library(raster)
r <- raster(sjutm, ncol=25, nrow=25)
rp <- as(r, 'SpatialPolygons')
显示
plot(sjutm, col='red')
lines(rp, col='blue')
要计算每个网格单元的案例数(在此处使用一些随机点),您不想使用多边形,而是要使用RasterLayer
set.seed(0)
x <- runif(500, xmin(r), xmax(r))
y <- runif(500, ymin(r), ymax(r))
xy1 <- cbind(x, y)
x <- runif(500, xmin(r), xmax(r))
y <- runif(500, ymin(r), ymax(r))
xy2 <- cbind(x, y)
d1 <- rasterize(xy1, r, fun="count", background=0)
d2 <- rasterize(xy2, r, fun="count", background=0)
plot(d1)
plot(sjutm, add=TRUE)
之后
s <- stack(d1, d2)
names(s) = c("assault", "theft")
s <- mask(s, sjutm)
plot(s, addfun=function()lines(sjutm))
要获得您想要的桌子
p <- rasterToPoints(s)
cell <- cellFromXY(s, p[,1:2])
res <- data.frame(grid_id=cell, p[,3:4])
head(res)
# grid_id assault theft
#1 1 1 1
#2 2 0 1
#3 3 0 3
#4 5 1 1
#5 6 1 0
#6 26 0 0
您还可以从结果中创建一个SpatialPolygonsDataFrame
pp <- as(s, 'SpatialPolygonsDataFrame')
pp
#class : SpatialPolygonsDataFrame
#features : 190
#extent : 584411.5, 623584.9, 4109499, 4147443 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=utm +zone=10 +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
#variables : 2
#names : assault, theft
#min values : 0, 0
#max values : 4, 5
答案 1 :(得分:4)
此外,这是一个基于sf和tidyverse的解决方案:
使用sf,您可以使用st_make_grid()
函数制作正方形网格。在这里,我将在圣何塞的边界框上绘制2公里的网格,然后将其与圣何塞的边界相交。请注意,我要投影到UTM区域10N,因此可以以米为单位指定网格大小。
library(tigris)
library(tidyverse)
library(sf)
options(tigris_class = "sf", tigris_use_cache = TRUE)
set.seed(1234)
sj <- places("CA", cb = TRUE) %>%
filter(NAME == "San Jose") %>%
st_transform(26910)
g <- sj %>%
st_make_grid(cellsize = 2000) %>%
st_intersection(sj) %>%
st_cast("MULTIPOLYGON") %>%
st_sf() %>%
mutate(id = row_number())
接下来,我们可以使用st_sample()
生成一些随机犯罪数据,并将其绘制出来以查看我们正在处理什么。
thefts <- st_sample(sj, size = 500) %>%
st_sf()
assaults <- st_sample(sj, size = 200) %>%
st_sf()
plot(g$geometry)
plot(thefts, add = TRUE, col = "red")
然后可以使用st_join()
在空间上将犯罪数据连接到网格。我们可以绘图以检查结果。
theft_grid <- g %>%
st_join(thefts) %>%
group_by(id) %>%
summarize(num_thefts = n())
plot(theft_grid["num_thefts"])
然后我们可以对攻击数据执行相同的操作,然后将两个数据集结合在一起以获得所需的结果。如果您有很多犯罪数据集,则可以对其进行修改以在purrr::map()
的某些变体中工作。
assault_grid <- g %>%
st_join(assaults) %>%
group_by(id) %>%
summarize(num_assaults = n())
st_geometry(assault_grid) <- NULL
crime_data <- left_join(theft_grid, assault_grid, by = "id")
crime_data
Simple feature collection with 190 features and 3 fields
geometry type: GEOMETRY
dimension: XY
bbox: xmin: 584412 ymin: 4109499 xmax: 625213.2 ymax: 4147443
epsg (SRID): 26910
proj4string: +proj=utm +zone=10 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs
# A tibble: 190 x 4
id num_thefts num_assaults geometry
<int> <int> <int> <GEOMETRY [m]>
1 1 2 1 POLYGON ((607150.3 4111499, 608412 4111499, 608412 4109738,…
2 2 4 1 POLYGON ((608412 4109738, 608412 4111499, 609237.8 4111499,…
3 3 3 1 POLYGON ((608412 4113454, 608412 4111499, 607150.3 4111499,…
4 4 2 2 POLYGON ((609237.8 4111499, 608412 4111499, 608412 4113454,…
5 5 1 1 MULTIPOLYGON (((610412 4112522, 610412 4112804, 610597 4112…
6 6 1 1 POLYGON ((616205.4 4113499, 616412 4113499, 616412 4113309,…
7 7 1 1 MULTIPOLYGON (((617467.1 4113499, 618107.9 4113499, 617697.…
8 8 2 1 POLYGON ((605206.8 4115499, 606412 4115499, 606412 4114617,…
9 9 5 1 POLYGON ((606412 4114617, 606412 4115499, 608078.2 4115499,…
10 10 1 1 POLYGON ((609242.7 4115499, 610412 4115499, 610412 4113499,…
# ... with 180 more rows
答案 2 :(得分:1)
如果您的目标只是可视化,而不一定是所有的网格聚合代码和数据,则可以在library(mapdeck)
中生成交互式地图和网格(请注意,您将需要Mapbox访问令牌)
生成数据的第一步是从@kwalkertcu的答案中借用的
library(tigris)
library(sf)
options(tigris_class = "sf", tigris_use_cache = TRUE)
set.seed(1234)
sj <- places("CA", cb = TRUE) %>%
filter(NAME == "San Jose") %>%
st_transform(26910)
thefts <- st_sample(sj, size = 500) %>%
st_sf() %>%
st_transform(crs = 4326)
## some random weight data
thefts$weight <- sample(1:100, size = nrow(thefts), replace = T)
然后,在给定sf
对象带有weight
列的情况下,您可以使用add_screengrid()
进行绘制
library(mapdeck)
set_token("MAPBOX_TOKEN")
mapdeck(
style = mapdeck_style("dark")
, location = c(-121.8, 37.3)
, zoom = 6
) %>%
add_screengrid(
data = thefts
, cell_size = 15
, weight = "weight"
)
注意: