R - 根据排名偏好分解覆盖区域数据

R - Disaggregate coverage area data based on a ranking preference

我在英国的地方当局级别拥有 4G 移动覆盖,占所覆盖地理区域的百分比(大约 200 个区域)。我想分解这些数据,以便我可以处理大约 9000 lower-level 个邮政编码扇区。

对我来说最合适的方法是首先将 4G 地理覆盖分配到人口最密集的地区,因为这最能代表移动运营商将如何投资市场。人口最少的地区最终将没有覆盖。但是,我正在为如何在 R 中执行此操作而苦苦挣扎。

我有一个类似这样的邮政编码扇区数据的数据框(我在这里使用了假设数据):

Name      pcd.sect  pop    area pop.dens  rank  
Cambridge   1      5546    0.6   8341      1     
Cambridge   2      7153    1.1   5970      2     
Cambridge   3      5621    2.3   5289      3     
Cambridge   4      10403   4.3   4361      4     
Cambridge   5      14796   4.2   3495      5     
...

然后我获取汇总的地方当局数据并将其放在每一行(添加右三列):

Name      pcd.sect  pop    area pop.dens  rank  LA.4G  LA.area   LA.4G(km2)
Cambridge   1      5546    0.6   8341      1     58     140        82
Cambridge   2      7153    1.1   5970      2     58     140        82  
Cambridge   3      5621    2.3   5289      3     58     140        82
Cambridge   4      10403   4.3   4361      4     58     140        82
Cambridge   5      14796   4.2   3495      5     58     140        82  
...

我不得不缩短标题,所以让我更详细地解释一下:

以剑桥为例,整个地方政府的4G覆盖率为58%。然后我想分解这个数字以实现各个邮政编码区域的 4G 覆盖。

理想情况下,数据最终看起来像这样,并为邮政编码扇区覆盖范围增加一列:

Name      pcd.sect  ...     pcd.sector.coverage (%)
Cambridge   1       ...         100
Cambridge   2       ...         100
Cambridge   3       ...         100
Cambridge   4       ...         34
Cambridge   5       ...         0
...        ...      ...         ... 

如何让 R 根据区域列将这 82 平方公里(58% 的地理覆盖范围)分配给新列中的邮政编码扇区,然后在达到 82 平方公里(58%)的最大覆盖水平后停止地理覆盖率百分比)?

这就是我对这个问题的解释。如果这不是你的意思,请纠正我。 假设你有以下数据。

dat <- data.frame(
  Name = "A", pcd.sector = 1:5,
  area = c(2, 3, 1, 5, 3), 
  areaSum = 14, LA.4G = 8
)
dat

#  Name pcd.sector area areaSum LA.4G
#1    A          1    2      14     8
#2    A          2    3      14     8
#3    A          3    1      14     8
#4    A          4    5      14     8
#5    A          5    3      14     8

你有五个扇区,有不同的区域。虽然加起来有14个,但4G覆盖的只有8个。您想分配扇区 1 到 5 的区域。

以下代码完成这项工作。我使用 cumsum 函数计算顶部扇区的面积累计和,该扇区受 4G 覆盖限制的限制。分配的区域可以通过 diff 函数计算,该函数采用向量的一步差。扇区 1 到 3 获得 100% 的覆盖率,总共有 6 个区域,因此只剩下 2 个。 4区虽然有5区,但只能享受2区,也就是40%。这用完了区域,扇区 5 没有留下任何东西。

dat$area_allocated <- diff(c(0, pmin(cumsum(dat$area), dat$LA.4G)))
dat$area_coverage  <- dat$area_allocated / dat$area * 100
dat

#   Name pcd.sector area areaSum LA.4G area_allocated area_coverage
# 1    A          1    2      14     8              2           100
# 2    A          2    3      14     8              3           100
# 3    A          3    1      14     8              1           100
# 4    A          4    5      14     8              2            40
# 5    A          5    3      14     8              0             0

如果您有很多区域,那么您可能需要使用 dplyr::group_by 功能。

dat <- rbind(
  data.frame(
    Name = "A", pcd.sector = 1:5,
    area = c(2, 3, 1, 5, 3), 
    areaSum = 14, LA.4G = 8
  ),
  data.frame(
    Name = "B", pcd.sector = 1:3,
    area = c(4, 3, 2), 
    areaSum = 9, LA.4G = 5
  )
)

library(dplyr)
dat <- dat %>% group_by(Name) %>% 
  mutate(area_allocated = diff(c(0, pmin(cumsum(area), LA.4G)))) %>%
  mutate(area_coverage = area_allocated / area * 100)
dat

#     Name pcd.sector  area areaSum LA.4G area_allocated area_coverage
#   <fctr>      <int> <dbl>   <dbl> <dbl>          <dbl>         <dbl>
# 1      A          1     2      14     8              2     100.00000
# 2      A          2     3      14     8              3     100.00000
# 3      A          3     1      14     8              1     100.00000
# 4      A          4     5      14     8              2      40.00000
# 5      A          5     3      14     8              0       0.00000
# 6      B          1     4       9     5              4     100.00000
# 7      B          2     3       9     5              1      33.33333
# 8      B          3     2       9     5              0       0.00000