如何迭代我的代码来计算每个城市的总街道长度 (OSM)?

How to iterate my code to calculate total street length (OSM) per city?

我有以下 R 代码,我想在名为 ucb.world.cities 的数据框上迭代它。该脚本为数据框的每个城市(行)计算步行街的总长度(基于 osm 数据),然后导出一个 .csv 文件,每个城市区域的结果以及一个 .shapefile 行的步行街。但是,数据框包含大约 996 个城市案例,我不想分别为每个城市手动重复该过程。因此,我欢迎任何关于如何迭代代码的想法。

    library(osmdata)
    library(sf)
    library(dplyr)

> head(ucb.world.cities)
# A tibble: 6 x 10
  ID_HDC_G0 BBX_LATMN BBX_LONMN BBX_LATMX BBX_LONMX  AREA XC_NM_LST UC_NM_MN                                 GRGN_L1 GRGN_L2        
      <dbl>     <dbl>     <dbl>     <dbl>     <dbl> <dbl> <chr>     <chr>                                    <chr>   <chr>          
1      3244      60.1      24.7      60.3      25.2   344 Finland   Helsinki [FIN]                           Europe  Northern Europe
2      2493      59.8      10.5      60.0      11.0   242 Norway    Oslo [NOR]                               Europe  Northern Europe
3      3396      59.8      30.1      60.1      30.6   527 Russia    Sankt Peterburg (Saint Petersburg) [RUS] Europe  Eastern Europe 
4      2973      59.2      17.8      59.5      18.3   361 Sweden    Stockholm [SWE]                          Europe  Northern Europe
5      3739      57.5      39.7      57.7      40.0   166 Russia    Yaroslavl [RUS]                          Europe  Eastern Europe 
6      5735      57.1      65.4      57.2      65.7   155 Russia    Tyumen [RUS]                             Europe  Eastern Europe 
> 

    q001<- opq(bbox=c(ucb.world.cities$BBX_LONMN[1], 
                               ucb.world.cities$BBX_LATMN[1], 
                               ucb.world.cities$BBX_LONMX[1], 
                               ucb.world.cities$BBX_LATMX[1])) %>%
        add_osm_feature(key="highway", value="pedestrian") 

        pedestrianA<- osmdata_sf(q001)
        pedestrianB<- pedestrianA[["osm_lines"]]
        pedestrianC<- subset(pedestrianB, name != "NA")

        city001<- st_geometry(pedestrianC)
        city001<- st_intersection(city001, ucb.world.cities_spatial)
        setwd("C:/Users/Alex/Desktop/R_Analysis_July2019/Shapefiles_PedestrianStreets_with_Address")
        st_write(city001, dsn = paste0(ucb.world.cities$UC_NM_MN[1],".shp"), driver = "ESRI Shapefile")
        city001_length<- st_length(city001)

        result001<- as.data.frame(sum(city001_length))
        colnames(result001)[1]<- "Pedestrian.Str.Names.meters"
        result001[, "UC_NM_MN"]<- paste0(ucb.world.cities$UC_NM_MN[1])      
        result001[, "ID_HDC_G0"]<- paste0(ucb.world.cities$ID_HDC_G0[1])
        setwd("C:/Users/Alex/Desktop/R_Analysis_July2019/Tables_PedestrianStreets_with_Address")
        write.csv(result001, file=paste0(ucb.world.cities$UC_NM_MN[1],".csv"))
for(i in 1:nrow(ucb.world.cities)){ # iterates from 1 : number of rows in your data frame

q001<- opq(bbox=c(ucb.world.cities$BBX_LONMN[i], #[i] will get index 1: to number of rows in your data frame 
                  ucb.world.cities$BBX_LATMN[i], 
                  ucb.world.cities$BBX_LONMX[i], 
                  ucb.world.cities$BBX_LATMX[i])) %>%
  add_osm_feature(key="highway", value="pedestrian") 

pedestrianA<- osmdata_sf(q001)
pedestrianB<- pedestrianA[["osm_lines"]]
pedestrianC<- subset(pedestrianB, name != "NA")

city001<- st_geometry(pedestrianC)
city001<- st_intersection(city001, ucb.world.cities_spatial)
setwd("C:/Users/Alex/Desktop/R_Analysis_July2019/Shapefiles_PedestrianStreets_with_Address")
st_write(city001, dsn = paste0(ucb.world.cities$UC_NM_MN[i],".shp"), driver = "ESRI Shapefile")
city001_length<- st_length(city001)

result001<- as.data.frame(sum(city001_length))
colnames(result001)[1]<- "Pedestrian.Str.Names.meters" #presume you want to rename just the first column here and not iterate over..
result001[, "UC_NM_MN"]<- paste0(ucb.world.cities$UC_NM_MN[i])      
result001[, "ID_HDC_G0"]<- paste0(ucb.world.cities$ID_HDC_G0[i])
setwd("C:/Users/Alex/Desktop/R_Analysis_July2019/Tables_PedestrianStreets_with_Address")
write.csv(result001, file=paste0(ucb.world.cities$UC_NM_MN[i],".csv"))

}

add_osm_feature(key="highway", value="pedestrian") 调用只提取明确标记为行人的高速公路,通常很少。 dodgr package 可以用来方便地给出你想要的答案,通过将一个 osmdata 网络转换成一个可路由的图,包括只为行人移动路由的能力,这将删除除了那些可通过的路径之外的所有路径行人。您所在城市之一的示例:

q001<- opq(bbox=c(ucb.world.cities$BBX_LONMN[i], 
              ucb.world.cities$BBX_LATMN[i], 
              ucb.world.cities$BBX_LONMX[i], 
              ucb.world.cities$BBX_LATMX[i])) %>%
    add_osm_feature(key="highway") %>% # all highways
    osmdata_sf()
library(dodgr)
net <- weight_streetnet (q001$osm_lines, wt_profile = "foot")

人行横道的总长度是 sum(net$d) - 但是 net 有两个方向的边缘,所以你需要

one_way <- which (net$oneway == "yes") # look at table(oneway) to see all values in your data
two_way <- which(!net$oneway == "yes") # or whatever other values you have
d <- sum(net$d[one_way]) + sum(net$d[two_way])/2

只需将其循环遍历每个城市即可获得所需的长度。