热图中的密度计数
Density count in heatmaps
我的热图有问题,它显示了密度水平,但没有说明密度计数。 (例如有多少个点在同一区域)。
我的数据分为更多列,但最重要的是:lat,lon。
我想要这样的东西,但是 "count" : ,
但是,当我尝试应用他在该答案中使用的代码时,我的最大-"level" 密度并不能反映我的密度计数。(例如,我收到 7500 的 Intead 6,即使我有成千上万的数据集中)。
那是我的代码:
us_map_g_str <- get_map(location = c(-90.0,41.5,-81.0,42.7), zoom = 7)
ggmap(us_map_g_str, extent = "device") +
geom_tile(data = data1, aes(x = as.numeric(lon), y = as.numeric(lat)), size = 0.3) +
stat_density2d(data = data1, aes(x = as.numeric(lon), y = as.numeric(lat), fill = ..level.., alpha = ..level..), size = 0.3, bins = 10, geom = "polygon") +
scale_fill_gradient(name= "Ios",low = "green", high = "red", trans= "exp") +
scale_alpha(range = c(0, 0.3), guide = FALSE)
这是我得到的:
这是部分数据:
lat lon tag device
1 43.33622 -83.67445 0 iPhone5
2 43.33582 -83.69964 0 iPhone5
3 43.33623 -83.68744 0 iPhone5
4 43.33584 -83.72186 0 iPhone5
5 43.33616 -83.67526 0 iPhone5
6 43.25040 -83.78234 0 iPhone5
("tag" 栏不重要)
修订
我意识到我之前的答案需要修改。所以,就在这里。如果你想找出一个轮廓的每一层有多少个数据点,你实际上有很多事情要做。如果您乐于使用下面的 leaflet
选项,您的生活会轻松得多。
首先,让我们获取底特律的地图,并创建一个示例数据框。
library(dplyr)
library(ggplot2)
library(ggmap)
mymap <- get_map(location = "Detroit", zoom = 8)
### Create a sample data
set.seed(123)
mydata <- data.frame(long = runif(min = -84, max = -82.5, n = 100),
lat = runif(min = 42, max = 42.7, n = 100))
现在,我们绘制一张地图并将其保存为g
。
g <- ggmap(mymap) +
stat_density2d(data = mydata,
aes(x = long, y = lat, fill = ..level..),
size = 0.5, bins = 10, geom = "polygon")
真正的工作从这里开始。为了找出所有级别的数据点数,您要使用 ggplot
生成的数据框。在这个数据框中,您有多边形的数据。这些多边形用于绘制水平线。您可以在下图中看到,我在地图上绘制了三个级别。
### Create a data frame so that we can find how many data points exist
### in each level.
mydf <- ggplot_build(g)$data[[4]]
### Check where the polygon lines are. This is just for a check.
check <- ggmap(mymap) +
geom_point(data = mydata, aes(x = long, y = lat)) +
geom_path(data = subset(mydf, group == "1-008"), aes(x = x, y = y)) +
geom_path(data = subset(mydf, group == "1-009"), aes(x = x, y = y)) +
geom_path(data = subset(mydf, group == "1-010"), aes(x = x, y = y))
下一步是为图例创建水平向量。我们按组对数据进行分组(例如 1-010
),并使用 slice()
为每个组取第一行。然后,取消数据分组并选择第 2 列。最后,创建一个向量
unlist()
。最后我们回到lev
。
mydf %>%
group_by(group) %>%
slice(1) %>%
ungroup %>%
select(2) %>%
unlist -> lev
现在我们按组拆分多边形数据(即 mydf),并为每个级别创建一个多边形。因为我们有 11 个级别(11 个多边形),所以我们使用 lapply()
。在lapply循环中,我们需要做的; 1) 提取经度和纬度列,2) 创建多边形,3) 将多边形转换为空间多边形,4) 分配
CRS,5) 创建一个虚拟数据框,以及 6) 创建 SpatialPolygonsDataFrames。
mylist <- split(mydf, f = mydf$group)
test <- lapply(mylist, function(x){
xy <- x[, c(3,4)]
circle <- Polygon(xy, hole = as.logical(NA))
SP <- SpatialPolygons(list(Polygons(list(circle), ID = "1")))
proj4string(SP) <- CRS("+proj=longlat +ellps=WGS84")
df <- data.frame(value = 1, row.names = "1")
circleDF <- SpatialPolygonsDataFrame(SP, data = df)
})
现在我们回到原始数据。我们需要做的是将数据框转换为 SpatialPointsDataFrame。这是因为我们需要对数据进行子集化并找出每个多边形(每个级别)中存在多少个数据点。首先,从你的 data.frame 获得长和纬度。确保顺序在 lon/lat.
xy <- mydata[,c(1,2)]
然后,我们创建 SPDF (SpatialPolygonsDataFrame)。您希望空间多边形和空间点数据之间具有相同的 proj4string。
spdf <- SpatialPointsDataFrame(coords = xy, data = mydata,
proj4string = CRS("+proj=longlat +ellps=WGS84"))
然后,我们使用每个多边形对数据 (mydata
) 进行子集化。
ana <- lapply(test, function(y){
mydf <- as.data.frame(spdf[y, ])
})
数据点在不同层级重叠;我们有重复。首先,我们尝试找出每个级别的唯一数据点。我们在ana中绑定数据框,创建一个数据框,就是foo1
。我们还创建了一个数据框,我们希望在其中找到唯一数量的数据点。我们确保 foo1
和 foo2
之间的列名完全相同。使用 setdiff()
和 nrow()
,我们可以找到每个级别中唯一的数据点数。
total <- lapply(11:2, function(x){
foo1 <- bind_rows(ana[c(11:x)])
foo2 <- as.data.frame(ana[x-1])
names(foo2) <- names(foo1)
nrow(setdiff(foo2, foo1))
})
最后,我们需要找到最内层的数据点数量,即第11层。我们在ana
中选择第11层的数据框并创建数据框并统计数量行数。
bob <- nrow(as.data.frame(ana[11]))
out <- c(bob,unlist(total))
### check if total is 100
### sum(out)
### [1] 100
我们将相反的 out
指定为 lev
的名称。这是因为我们想在图例中显示每个级别存在多少个数据点。
names(lev) <- rev(out)
现在我们可以添加图例了。
final <- g +
scale_fill_continuous(name = "Total",
guide = guide_legend(),
breaks = lev)
final
传单选项
如果您使用传单包,您可以将具有不同缩放比例的数据点分组。 Leaflet 统计了某些区域的数据点,并用圆圈表示数字,如下图所示。放大得越多,传单将数据点分解成小组的次数就越多。就工作量而言,这要轻得多。此外,您的地图是交互式的。这可能是更好的选择。
library(leaflet)
leaflet(mydf) %>%
addTiles() %>%
addMarkers(clusterOptions = markerClusterOptions())
我的热图有问题,它显示了密度水平,但没有说明密度计数。 (例如有多少个点在同一区域)。
我的数据分为更多列,但最重要的是:lat,lon。
我想要这样的东西,但是 "count" : , 但是,当我尝试应用他在该答案中使用的代码时,我的最大-"level" 密度并不能反映我的密度计数。(例如,我收到 7500 的 Intead 6,即使我有成千上万的数据集中)。 那是我的代码:
us_map_g_str <- get_map(location = c(-90.0,41.5,-81.0,42.7), zoom = 7)
ggmap(us_map_g_str, extent = "device") +
geom_tile(data = data1, aes(x = as.numeric(lon), y = as.numeric(lat)), size = 0.3) +
stat_density2d(data = data1, aes(x = as.numeric(lon), y = as.numeric(lat), fill = ..level.., alpha = ..level..), size = 0.3, bins = 10, geom = "polygon") +
scale_fill_gradient(name= "Ios",low = "green", high = "red", trans= "exp") +
scale_alpha(range = c(0, 0.3), guide = FALSE)
这是我得到的:
这是部分数据:
lat lon tag device
1 43.33622 -83.67445 0 iPhone5
2 43.33582 -83.69964 0 iPhone5
3 43.33623 -83.68744 0 iPhone5
4 43.33584 -83.72186 0 iPhone5
5 43.33616 -83.67526 0 iPhone5
6 43.25040 -83.78234 0 iPhone5
("tag" 栏不重要)
修订
我意识到我之前的答案需要修改。所以,就在这里。如果你想找出一个轮廓的每一层有多少个数据点,你实际上有很多事情要做。如果您乐于使用下面的 leaflet
选项,您的生活会轻松得多。
首先,让我们获取底特律的地图,并创建一个示例数据框。
library(dplyr)
library(ggplot2)
library(ggmap)
mymap <- get_map(location = "Detroit", zoom = 8)
### Create a sample data
set.seed(123)
mydata <- data.frame(long = runif(min = -84, max = -82.5, n = 100),
lat = runif(min = 42, max = 42.7, n = 100))
现在,我们绘制一张地图并将其保存为g
。
g <- ggmap(mymap) +
stat_density2d(data = mydata,
aes(x = long, y = lat, fill = ..level..),
size = 0.5, bins = 10, geom = "polygon")
真正的工作从这里开始。为了找出所有级别的数据点数,您要使用 ggplot
生成的数据框。在这个数据框中,您有多边形的数据。这些多边形用于绘制水平线。您可以在下图中看到,我在地图上绘制了三个级别。
### Create a data frame so that we can find how many data points exist
### in each level.
mydf <- ggplot_build(g)$data[[4]]
### Check where the polygon lines are. This is just for a check.
check <- ggmap(mymap) +
geom_point(data = mydata, aes(x = long, y = lat)) +
geom_path(data = subset(mydf, group == "1-008"), aes(x = x, y = y)) +
geom_path(data = subset(mydf, group == "1-009"), aes(x = x, y = y)) +
geom_path(data = subset(mydf, group == "1-010"), aes(x = x, y = y))
下一步是为图例创建水平向量。我们按组对数据进行分组(例如 1-010
),并使用 slice()
为每个组取第一行。然后,取消数据分组并选择第 2 列。最后,创建一个向量
unlist()
。最后我们回到lev
。
mydf %>%
group_by(group) %>%
slice(1) %>%
ungroup %>%
select(2) %>%
unlist -> lev
现在我们按组拆分多边形数据(即 mydf),并为每个级别创建一个多边形。因为我们有 11 个级别(11 个多边形),所以我们使用 lapply()
。在lapply循环中,我们需要做的; 1) 提取经度和纬度列,2) 创建多边形,3) 将多边形转换为空间多边形,4) 分配
CRS,5) 创建一个虚拟数据框,以及 6) 创建 SpatialPolygonsDataFrames。
mylist <- split(mydf, f = mydf$group)
test <- lapply(mylist, function(x){
xy <- x[, c(3,4)]
circle <- Polygon(xy, hole = as.logical(NA))
SP <- SpatialPolygons(list(Polygons(list(circle), ID = "1")))
proj4string(SP) <- CRS("+proj=longlat +ellps=WGS84")
df <- data.frame(value = 1, row.names = "1")
circleDF <- SpatialPolygonsDataFrame(SP, data = df)
})
现在我们回到原始数据。我们需要做的是将数据框转换为 SpatialPointsDataFrame。这是因为我们需要对数据进行子集化并找出每个多边形(每个级别)中存在多少个数据点。首先,从你的 data.frame 获得长和纬度。确保顺序在 lon/lat.
xy <- mydata[,c(1,2)]
然后,我们创建 SPDF (SpatialPolygonsDataFrame)。您希望空间多边形和空间点数据之间具有相同的 proj4string。
spdf <- SpatialPointsDataFrame(coords = xy, data = mydata,
proj4string = CRS("+proj=longlat +ellps=WGS84"))
然后,我们使用每个多边形对数据 (mydata
) 进行子集化。
ana <- lapply(test, function(y){
mydf <- as.data.frame(spdf[y, ])
})
数据点在不同层级重叠;我们有重复。首先,我们尝试找出每个级别的唯一数据点。我们在ana中绑定数据框,创建一个数据框,就是foo1
。我们还创建了一个数据框,我们希望在其中找到唯一数量的数据点。我们确保 foo1
和 foo2
之间的列名完全相同。使用 setdiff()
和 nrow()
,我们可以找到每个级别中唯一的数据点数。
total <- lapply(11:2, function(x){
foo1 <- bind_rows(ana[c(11:x)])
foo2 <- as.data.frame(ana[x-1])
names(foo2) <- names(foo1)
nrow(setdiff(foo2, foo1))
})
最后,我们需要找到最内层的数据点数量,即第11层。我们在ana
中选择第11层的数据框并创建数据框并统计数量行数。
bob <- nrow(as.data.frame(ana[11]))
out <- c(bob,unlist(total))
### check if total is 100
### sum(out)
### [1] 100
我们将相反的 out
指定为 lev
的名称。这是因为我们想在图例中显示每个级别存在多少个数据点。
names(lev) <- rev(out)
现在我们可以添加图例了。
final <- g +
scale_fill_continuous(name = "Total",
guide = guide_legend(),
breaks = lev)
final
传单选项
如果您使用传单包,您可以将具有不同缩放比例的数据点分组。 Leaflet 统计了某些区域的数据点,并用圆圈表示数字,如下图所示。放大得越多,传单将数据点分解成小组的次数就越多。就工作量而言,这要轻得多。此外,您的地图是交互式的。这可能是更好的选择。
library(leaflet)
leaflet(mydf) %>%
addTiles() %>%
addMarkers(clusterOptions = markerClusterOptions())