【问题标题】:How to Calculate Crime Density?如何计算犯罪密度?
【发布时间】:2018-08-06 14:08:15
【问题描述】:

总体目标:计算美国城市网格结构中的犯罪密度。每个方格应为 100 平方米。我有一个数据框 crime.inc 列出了个人犯罪实例 lat 和 lon;像这样:

incident id   lat       lon
1001         45.123   -122.456
1002         45.456   -122.789

接下来,我有一个预定义的网格 g,它是一个常规网格

predef.grid <- data.frame(lat = seq(from = 44, to = 45, by = 0.1),lon = seq(from = -122, to = -121, by = 0.1))
id <- rownames(predef.grid)  # add row ids
predef.grid <- cbind(id=id, predef.grid)  # add row ids

我的输出需要是这样的,每一行都是预定义网格中的一个唯一网格,计数是该网格中的事件数:

id      lat   lon       count
1001  45.123  -122.789    4
1002  45.456  -122.987    5

我尝试过以各种形式使用 sp、sf、raster、rgeos,但始终无法将岩石翻过山坡!任何帮助将不胜感激!

【问题讨论】:

  • 您能解释一下您的predef.grid 对象是如何表示一个100m 正方形的网格的吗?
  • @sebdalgarno 网格松散地基于与纬度/经度坐标相关的 0.001 大约 = 100m 的逻辑。所以从 45.123 到 45.124 的变化大约是 100m。这不准确,我上面的例子没有反映这个逻辑

标签: r gis geospatial sp sf


【解决方案1】:

“与纬度/经度坐标相关的 0.001 约为 100m”的假设可能站不住脚。距离将取决于您在世界的哪个位置,但使用您所在地区的示例数据:

library(sf)

# adjust latitude by 0.001
df <- data.frame(lat = c(45.123, 45.124),  lon = c(-122.789, -122.789))
df.sf <- st_as_sf(df, coords = c("lon", "lat"), crs = 4326)
> st_distance(df.sf)
Units: m
         [,1]     [,2]
[1,]   0.0000 111.1342
[2,] 111.1342   0.0000

#Or, if we adjust the longitude by 0.001:
df <- data.frame(lat = c(45.123, 45.123),  lon = c(-122.789, -122.790))
df.sf <- st_as_sf(df, coords = c("lon", "lat"), crs = 4326)
> st_distance(df.sf)
Units: m
         [,1]     [,2]
[1,]  0.00000 78.67796
[2,] 78.67796  0.00000

这里是使用sf 包的替代解决方案:

# add a few more points to make it more interesting
df <- data.frame(id = c(1001, 1002, 1003, 1004, 1005),
                 lat = c(45.123, 45.123, 45.126, 45.121, 45.130), 
                 lon = c(-122.456, -122.457, -122.444, -122.442, -122.445))

# convert to an sf object and set projection (crs) to 4326 (lon/lat)
df.sf <- st_as_sf(df, coords = c("lon", "lat"), crs = 4326)

# transform to UTM (Zone 10) for distance
df.utm <- st_transform(df.sf, "+proj=utm +zone=10 +datum=WGS84 +units=m +no_defs")

# create a 100m grid on these points
grid.100 <- st_make_grid(x = df.utm, cellsize = c(100, 100))

# plot to make sure
library(ggplot2)
ggplot() +
  geom_sf(data = df.utm, size = 3) +
  geom_sf(data = grid.100, alpha = 0)

# 将网格转换为 sf(不是 sfc)并添加一个 id 列 grid.sf

# find how many points intersect each grid cell by using lengths() to get the number of points that intersect each grid square
grid.sf$count <- st_intersects(grid.sf, df.utm) %>% lengths()

要检查的情节

ggplot() +
  geom_sf(data = grid.sf, alpha = 0.5, aes(fill = as.factor(count))) +
  geom_sf(data = df.utm, size = 3) +
  scale_fill_discrete("Number of Points")

【讨论】:

  • 谢谢!是的,0.001 = 100m 的假设并不准确。它更像是网格间距的一般参数(出于我的目的)。非常感谢您对 sf() 的洞察!
  • 很高兴它帮助了@beavertrapper07。如果确实回答了您的问题,请不要忘记标记为“已回答”。
  • 如何将 sf.grid 中的 UTM 距离数字转换回实际的纬度、经度坐标?试图在实际纬度/经度中找到每个网格的质心@sebdalgarno
  • 您可以使用st_transform(sf.grid, 4326) 转换回纬度/经度,其中 4326 是 WGS 84 的 epsg
【解决方案2】:

对于问题上的数据表明,经纬度只有三位小数。因此,您可以简单地使用 dplyr 按位置分组,而不需要使用 GIS 包。

library(dplyr)
densities <- crime.inc %>% group_by(lat,lon) %>% 
             summarise(count=n())

这样您会丢失 ID。如果你想保留 ID

library(dplyr)
densities <- crime.inc %>% group_by(lat,lon) %>% 
             rename(count=n())

【讨论】:

  • 安德烈·科斯塔 是的!这替换了我的 500 多行不起作用的代码!非常感谢
  • 不,这不是一个 100m 的网格。您甚至不能在常规的经纬坐标中拥有常规的 100m x 100m 网格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-16
相关资源
最近更新 更多