【问题标题】:Density count in heatmaps热图中的密度计数
【发布时间】:2015-09-11 11:27:27
【问题描述】:

我的热图有问题,它显示了密度 LEVEL,但没有说明密度计数。 (例如同一区域有多少点)。

我的数据分为更多列,但最重要的是:lat,lon。

我想要这样的东西,但是用“count”:https://stackoverflow.com/a/24615674/5316566, 但是,当我尝试应用他在该答案中使用的代码时,我的最大“级别”密度并不能反映我的密度计数。(即使我有成千上万的数据集中,我也会收到 7500,例如 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

(“标签”列不重要)

【问题讨论】:

  • 您想在哪里添加计数?你能分享你的部分数据吗?
  • 在图例中,而不是级别。我希望 R 计算浓度并告诉我他可以在一个区域中计算多少点。
  • 我想你在应用 hs 代码时忘记了一件事:他的数据有一个“计数”列。所以你需要操纵你的数据来拥有一个。
  • 数据框中的列如何命名并不重要,因为我以后可以随时更改它

标签: r ggplot2 ggmap


【解决方案1】:

修订

我意识到我之前的答案需要修改。所以,就在这里。如果你想知道一个轮廓的每一层有多少数据点,你实际上有很多事情要做。如果您乐于使用下面的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() 获取每个组的第一行。然后,取消分组数据并选择第二列。最后,创建一个向量 与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 中获取 long 和 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。我们还创建了一个数据框,我们想要找到唯一数量的数据点。我们确保foo1foo2 之间的列名完全相同。使用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())

【讨论】:

  • 您的第一次编辑效果不佳,但第二种方法很完美!甚至比热图更好。谢谢,非常感谢
  • @U.Cremona 我很高兴听到传单版本对您有用。 :)
  • 您知道如何自定义标记中显示的值吗?如果我想让他们显示另一列数据,我该怎么办?
  • @U.Cremona 恐怕我现在不知道。
  • 没问题的人 ;) 对于任何阅读我之前表达得很糟糕的评论的其他人:我想插入一个从列中获取数据的公式,并且标记必须显示结果跨度>
猜你喜欢
  • 2017-02-06
  • 2016-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 2013-07-08
  • 1970-01-01
相关资源
最近更新 更多