In the first section, you need to select one Census Tract that you think is the most walkable and another one that you think is least walkable within Fulton and DeKalb Counties, GA. As long as the two Census Tracts are within the two counties, you can pick any two you want. If the area you want to use as walkable/unwalkable area is not well-covered by one Census Tract, you can select multiple tracts (e.g., selecting three adjacent tracts as one walkable area). The definition of ‘walkable’ can be your own - you can choose solely based on your experience (e.g., had best/worst walking experience), refer to Walk Score, or any other mix of criteria you want. After you make the selection, provide a short write-up of why you chose those Census Tracts.
The second section is the main part of this assignment in which you prepare OSM data, download GSV images, apply computer vision.
In the third section, you will summarise and analyze the output and provide your findings. After you apply computer vision to the images, you will have the number of pixels in each image that represent 150 categories in your data. You will focus on the following categories in your analysis: building, sky, tree, road, and sidewalk. Specifically, you will (1) create maps to visualize the spatial distribution of different objects, (2) compare the mean of each category between the two Census Tract and (3) draw boxplots to compare the distributions.
Provide a brief description of your census tracts. Why do you think the Census Tracts are walkable and unwalkable? What were the contributing factors?
Fill out the template to complete the script.
library(tidyverse)
library(tidycensus)
library(osmdata)
library(sfnetworks)
library(units)
library(sf)
library(tidygraph)
library(tmap)
library(dotenv)
library(viridis)
library(dplyr)
library(ggplot2)
library(units)
library(leaflet)
library(leafsync)
library(dbscan)
library(tigris)
library(plotly)
library(here)
library(patchwork)
#endTest
The getbb() function, which we used in the class
material to download OSM data, isn’t suitable for downloading just two
Census Tracts. We will instead use an alternative method.
# TASK ////////////////////////////////////////////////////////////////////////
# 1. Set up your api key here
#census_api_key(Sys.getenv("census_api"))
load_dot_env("maj2.env")
## Warning in readLines(file): incomplete final line found on 'maj2.env'
CENSUS_API_KEY=Sys.getenv("CENSUS_API_KEY")
# //TASK //////////////////////////////////////////////////////////////////////
# =========== NO MODIFICATION ZONE STARTS HERE ===============================
# Download Census Tract polygon for Fulton and DeKalb
tract <- get_acs("tract",
variables = c('tot_pop' = 'B01001_001'),
year = 2020,
state = "GA",
county = c("Fulton", "DeKalb"),
geometry = TRUE)
## Getting data from the 2016-2020 5-year ACS
## Downloading feature geometry from the Census website. To cache shapefiles for use in future sessions, set `options(tigris_use_cache = TRUE)`.
##
|
| | 0%
|
| | 1%
|
|= | 1%
|
|== | 3%
|
|=== | 4%
|
|==== | 6%
|
|===== | 7%
|
|====== | 8%
|
|======= | 10%
|
|======== | 11%
|
|========= | 13%
|
|========== | 14%
|
|=========== | 16%
|
|============ | 17%
|
|============= | 19%
|
|============== | 20%
|
|=============== | 22%
|
|================ | 23%
|
|================= | 24%
|
|================== | 25%
|
|=================== | 27%
|
|==================== | 28%
|
|===================== | 30%
|
|====================== | 31%
|
|======================= | 33%
|
|======================== | 34%
|
|========================= | 36%
|
|========================== | 37%
|
|=========================== | 39%
|
|============================ | 40%
|
|============================= | 41%
|
|============================== | 42%
|
|=============================== | 44%
|
|================================ | 45%
|
|================================= | 47%
|
|================================== | 48%
|
|=================================== | 50%
|
|==================================== | 51%
|
|===================================== | 53%
|
|====================================== | 54%
|
|======================================= | 56%
|
|======================================== | 57%
|
|========================================= | 58%
|
|========================================== | 59%
|
|=========================================== | 61%
|
|============================================ | 62%
|
|============================================= | 64%
|
|============================================== | 65%
|
|=============================================== | 67%
|
|================================================ | 68%
|
|================================================= | 70%
|
|================================================== | 71%
|
|=================================================== | 73%
|
|==================================================== | 74%
|
|===================================================== | 75%
|
|====================================================== | 76%
|
|======================================================= | 78%
|
|======================================================= | 79%
|
|======================================================== | 80%
|
|========================================================= | 81%
|
|========================================================= | 82%
|
|=========================================================== | 84%
|
|=========================================================== | 85%
|
|============================================================= | 87%
|
|============================================================= | 88%
|
|=============================================================== | 90%
|
|=============================================================== | 91%
|
|================================================================= | 92%
|
|================================================================= | 93%
|
|=================================================================== | 95%
|
|=================================================================== | 96%
|
|==================================================================== | 98%
|
|===================================================================== | 98%
|
|===================================================================== | 99%
|
|======================================================================| 100%
# =========== NO MODIFY ZONE ENDS HERE ========================================
# TASK ////////////////////////////////////////////////////////////////////////
# The purpose of this TASK is to create one bounding box for walkable Census Tract and another bounding box for unwalkable Census Tract.
# As long as you generate what's needed for the subsequent codes, you are good. The numbered list of tasks below is to provide some hints.
# 1. Write the GEOID of walkable & unwalkable Census Tracts. e.g., tr1_ID <- c("13121001205", "13121001206")
# 2. Extract the selected Census Tracts using tr1_ID & tr2_ID
# 3. Create their bounding boxes using st_bbox(), and
# 4. assign them to tract_1_bb and tract_1_bb, respectively.
# For the walkable Census Tract(s)
# 1.
#test <- tract2 %>%
#Midtown Atlanta 1205 and 1206 are Census Tracts in midtown Atlanta bounded by 10th ST to the North. North Ave to the south, Juniper st to the east, and West Peachtree St to the west.
#Bounded by North Ave Marta Station to the south and Midtown Marta Station to the North
tr1_ID <- c("13121001205", "13121001206")
tract[tract$GEOID == tr1_ID,]
## Simple feature collection with 1 feature and 5 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -84.3878 ymin: 33.77725 xmax: -84.3825 ymax: 33.78175
## Geodetic CRS: NAD83
## GEOID NAME variable estimate moe
## 26 13121001206 Census Tract 12.06, Fulton County, Georgia tot_pop 3160 594
## geometry
## 26 MULTIPOLYGON (((-84.3878 33...
tractWalkable <- tract[tract$GEOID == tr1_ID,]
tractWalkable2<- tract %>% filter(GEOID==tr1_ID) %>% st_bbox()
tractWalkable2
## xmin ymin xmax ymax
## -84.38780 33.77725 -84.38250 33.78175
# 2~4
tract_1_bb <- tract %>% filter(GEOID==tr1_ID) %>% st_bbox()
# **YOUR CODE HERE..**
# For the unwalkable Census Tract(s)
# 1. Chatahoochee Hills Fulton County
tr2_ID <- "13121010402"
# 2~4
tract_2_bb <- tract %>% filter(GEOID==tr2_ID) %>% st_bbox()
# **YOUR CODE HERE..**
# //TASK //////////////////////////////////////////////////////////////////////
# =========== NO MODIFICATION ZONE STARTS HERE ===============================
# Get OSM data for the two bounding box
osm_1 <- opq(bbox = tract_1_bb) %>%
add_osm_feature(key = 'highway',
value = c("motorway", "trunk", "primary",
"secondary", "tertiary", "unclassified",
"residential")) %>%
osmdata_sf() %>%
osm_poly2line()
osm_2 <- opq(bbox = tract_2_bb) %>%
add_osm_feature(key = 'highway',
value = c("motorway", "trunk", "primary",
"secondary", "tertiary", "unclassified",
"residential")) %>%
osmdata_sf() %>%
osm_poly2line()
# =========== NO MODIFY ZONE ENDS HERE ========================================
tmap_mode('plot')
## tmap mode set to plotting
tm_shape(osm_1$osm_lines) + tm_lines(col = "highway")
tmap_mode('plot')
## tmap mode set to plotting
tm_shape(osm_2$osm_lines) + tm_lines(col = "highway")
# TASK ////////////////////////////////////////////////////////////////////////
# 1. Convert osm_1 and osm_2 to sfnetworks objects (set directed = FALSE)
# 2. Clean the network by (1) deleting parallel lines and loops, (2) create missing nodes, and (3) remove pseudo nodes,
# 3. Add a new column named length using edge_length() function.
net1 <- osm_1$osm_lines %>%
sfnetworks::as_sfnetwork(directed = FALSE) %>%
activate("edges") %>%
filter(!edge_is_multiple()) %>%
filter(!edge_is_loop()) %>%
convert(., sfnetworks::to_spatial_subdivision) %>%
convert(., sfnetworks::to_spatial_smooth) %>%
mutate(length = edge_length())
## Warning: to_spatial_subdivision assumes attributes are constant over geometries
net2 <- osm_2$osm_lines %>%
sfnetworks::as_sfnetwork(directed = FALSE) %>%
activate("edges") %>%
filter(!edge_is_multiple()) %>%
filter(!edge_is_loop()) %>%
convert(., sfnetworks::to_spatial_subdivision) %>%
convert(., sfnetworks::to_spatial_smooth) %>%
mutate(length = edge_length())
## Warning: to_spatial_subdivision assumes attributes are constant over geometries
# **YOUR CODE HERE..**
# //TASK //////////////////////////////////////////////////////////////////////
# =========== NO MODIFICATION ZONE STARTS HERE ===============================
# OSM for the walkable part
edges_1 <- net1 %>%
# Extract 'edges'
st_as_sf("edges") %>%
# Drop redundant columns
select(osm_id, highway,length) %>%
# Drop segments that are too short (100m)
mutate(length = as.vector(length))%>%
filter(length > 50) %>%
# Add a unique ID for each edge
mutate(edge_id = seq(1,nrow(.)),
is_walkable = "walkable")
# OSM for the unwalkable part
edges_2 <- net2 %>%
# Extract 'edges'
st_as_sf("edges") %>%
# Drop redundant columns
select(osm_id, highway, length) %>%
# Drop segments that are too short (100m)
mutate(length = as.vector(length))%>%
filter(length > 50) %>%
# Add a unique ID for each edge
mutate(edge_id = seq(1,nrow(.)),
is_walkable = "unwalkable")
# Merge the two
edges <- bind_rows(edges_1, edges_2)
# =========== NO MODIFY ZONE ENDS HERE ========================================
edges
## Simple feature collection with 1170 features and 5 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: -84.90465 ymin: 33.48209 xmax: -84.37941 ymax: 33.78449
## Geodetic CRS: WGS 84
## # A tibble: 1,170 × 6
## osm_id highway length geometry edge_id is_wa…¹
## * <chr> <chr> <dbl> <LINESTRING [°]> <int> <chr>
## 1 9248393 residential 138. (-84.38729 33.77802, -84.38742 33… 1 walkab…
## 2 9253622 residential 138. (-84.38729 33.77755, -84.38741 33… 2 walkab…
## 3 9255480 residential 132. (-84.38729 33.77755, -84.38718 33… 3 walkab…
## 4 9255480 residential 135. (-84.38587 33.77745, -84.38582 33… 4 walkab…
## 5 9267357 residential 139. (-84.38751 33.78073, -84.38762 33… 5 walkab…
## 6 9268354 residential 141. (-84.38122 33.77833, -84.38198 33… 6 walkab…
## 7 9268354 residential 146. (-84.38274 33.77843, -84.38282 33… 7 walkab…
## 8 9268354 residential 135. (-84.38431 33.77852, -84.38444 33… 8 walkab…
## 9 9268354 residential 142. (-84.38576 33.77862, -84.38582 33… 9 walkab…
## 10 9269517 residential 93.6 (-84.38491 33.78158, -84.38487 33… 10 walkab…
## # … with 1,160 more rows, and abbreviated variable name ¹is_walkable
## # ℹ Use `print(n = ...)` to see more rows
test_edge = 25
e <- edges %>% filter(edge_id == test_edge) %>% filter(is_walkable == "walkable")
tmap_mode('view')
## tmap mode set to interactive viewing
e %>% st_coordinates() %>%
as.data.frame() %>%
st_as_sf(coords = c("X", "Y"), crs = 4326) %>%
with(
tm_shape(.) + tm_dots() +
tm_shape(.[1,]) + tm_dots(col = "red") + # Start = red
tm_shape(.[nrow(.),]) + tm_dots(col = "yellow") # End = yellow
)
get_azi <- function(line){
# This function takes one edge (i.e., a street segment) as an input and
# outputs a data frame with four points (start, mid1, mid2, and end) and their azimuth.
# TASK ////////////////////////////////////////////////////////////////////////
# 1. From `line` object, extract the coordinates using st_coordinates() and extract the first two rows.
# 2. Use atan2() function to calculate the azimuth in degree.
# Make sure to adjust the value such that 0 is north, 90 is east, 180 is south, and 270 is west.
# 1
start_p <- line %>% st_coordinates() %>% .[1:2,1:2]
# **YOUR CODE HERE..**
# 2
start_azi <- atan2(start_p[2,"X"] - start_p[1, "X"],
start_p[2,"Y"] - start_p[1, "Y"])*180/pi# **YOUR CODE HERE..** --> For example, atan2()..
# //TASK //////////////////////////////////////////////////////////////////////
# TASK ////////////////////////////////////////////////////////////////////////
# Repeat what you did above, but for last two rows (instead of the first two rows).
# Remember to flip the azimuth so that the camera would be looking at the street that's being measured
end_p <- line %>%
st_coordinates() %>%
.[(nrow(.)-1):nrow(.),1:2]
end_azi <- atan2(end_p[2,"X"] - end_p[1, "X"],
end_p[2,"Y"] - end_p[1, "Y"])*180/pi
# **YOUR CODE HERE..** --> For example, atan2()..
end_azi <- if (end_azi < 180) {end_azi + 180} else {end_azi - 180}
# //TASK //////////////////////////////////////////////////////////////////////
# TASK ////////////////////////////////////////////////////////////////////////
# 1. From `line` object, use st_line_sample() function to generate points at 0.45 and 0.55 locations. These two points will be used to calculate the azimuth.
# 2. Use st_case() function to convert 'MULTIPOINT' object to 'POINT' object.
# 3. Extract coordinates using st_coordinates().
# 4. Use atan2() functino to Calculate azimuth.
# 5. Use st_line_sample() again to generate a point at 0.5 location and get its coordinates. This point will be the location at which GSV image will be downloaded.
mid_p <- line %>%
st_line_sample(sample = c(0.45, 0.55)) %>%
st_cast("POINT") %>%
st_coordinates()
mid_azi <- atan2(mid_p[2,"X"] - mid_p[1, "X"],
mid_p[2,"Y"] - mid_p[1, "Y"])*180/pi
mid_p <- line %>% st_line_sample(sample = 0.5) %>%
st_coordinates() %>%
.[1,1:2]
# **YOUR CODE HERE..** --> For 0.5 point
# //TASK //////////////////////////////////////////////////////////////////////
# =========== NO MODIFICATION ZONE STARTS HERE ===============================
return(tribble(
~type, ~X, ~Y, ~azi,
"start", start_p[1,"X"], start_p[1,"Y"], start_azi,
"mid1", mid_p["X"], mid_p["Y"], mid_azi,
"mid2", mid_p["X"], mid_p["Y"], ifelse(mid_azi < 180, mid_azi + 180, mid_azi - 180),
"end", end_p[2,"X"], end_p[2,"Y"], end_azi))
# =========== NO MODIFY ZONE ENDS HERE ========================================
}
We can apply get_azi() function to the edges object. We
finally append edges object to make use of the columns in
edges object (e.g., is_walkable column). When
you are finished with this code chunk, you will be ready to download GSV
images.
# TASK ////////////////////////////////////////////////////////////////////////
# Apply get_azi() function to all edges.
# Remember that you need to pass edges object to st_geometry()
# before you apply get_azi()
endp_azi <- edges %>%
st_geometry() %>%
map_df(get_azi)
# //TASK //////////////////////////////////////////////////////////////////////
# =========== NO MODIFICATION ZONE STARTS HERE ===============================
endp <- endp_azi %>%
bind_cols(edges %>%
st_drop_geometry() %>%
slice(rep(1:nrow(edges),each=4))) %>%
st_as_sf(coords = c("X", "Y"), crs = 4326, remove=FALSE) %>%
mutate(node_id = seq(1, nrow(.)))
# =========== NO MODIFY ZONE ENDS HERE ========================================
endp
## Simple feature collection with 4680 features and 10 fields
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: -84.90465 ymin: 33.48209 xmax: -84.37941 ymax: 33.78449
## Geodetic CRS: WGS 84
## # A tibble: 4,680 × 11
## type X Y azi osm_id highway length edge_id is_walkable
## * <chr> <dbl> <dbl> <dbl> <chr> <chr> <dbl> <int> <chr>
## 1 start -84.4 33.8 -88.7 9248393 residential 138. 1 walkable
## 2 mid1 -84.4 33.8 -89.1 9248393 residential 138. 1 walkable
## 3 mid2 -84.4 33.8 90.9 9248393 residential 138. 1 walkable
## 4 end -84.4 33.8 92.6 9248393 residential 138. 1 walkable
## 5 start -84.4 33.8 -85.1 9253622 residential 138. 2 walkable
## 6 mid1 -84.4 33.8 -88.7 9253622 residential 138. 2 walkable
## 7 mid2 -84.4 33.8 91.3 9253622 residential 138. 2 walkable
## 8 end -84.4 33.8 90.7 9253622 residential 138. 2 walkable
## 9 start -84.4 33.8 94.9 9255480 residential 132. 3 walkable
## 10 mid1 -84.4 33.8 94.3 9255480 residential 132. 3 walkable
## # … with 4,670 more rows, and 2 more variables: geometry <POINT [°]>,
## # node_id <int>
## # ℹ Use `print(n = ...)` to see more rows, and `colnames()` to see all variable names
#here("major2Images")
get_image <- function(iterrow){
# This function takes one row of endp and downloads GSV image using the information from endp.
# TASK ////////////////////////////////////////////////////////////////////////
# Finish this function definition.
# 1. Extract required information from the row of endp, including
# type (i.e., start, mid1, mid2, end), location, heading, edge_id, node_id, source (i.e., outdoor vs. default) and key.
# 2. Format the full URL and store it in furl. Refer to this page: https://developers.google.com/maps/documentation/streetview/request-streetview
# 3. Format the full path (including the file name) of the image being downloaded and store it in fpath
type = iterrow$type
location <- paste0(iterrow$Y %>% round(4), ",", iterrow$X %>% round(4))
heading <- iterrow$azi %>% round(1)
edge_id <- iterrow$edge_id
node_id <- iterrow$node_id
key <- Sys.getenv("GOOGLE_MAPS_API")
furl <- glue::glue("https://maps.googleapis.com/maps/api/streetview?size=640x640&location={location}&heading={heading}&fov=90&pitch=0&key={key}")
fname <- glue::glue("GSV-nid_{node_id}-eid_{edge_id}-type_{type}-Location_{location}-heading_{heading}.jpg") # Don't change this code for fname
fpath <- here("major2Images", fname)# **YOUR CODE HERE..**
# //TASK //////////////////////////////////////////////////////////////////////
# =========== NO MODIFICATION ZONE STARTS HERE ===============================
# Download images
if (!file.exists(fpath)){
download.file(furl, fpath, mode = 'wb')
}
# =========== NO MODIFY ZONE ENDS HERE ========================================
}
Before you download GSV images, make sure
the row number of endp is not too large! The row number of
endp will be the number of GSV images you will be
downloading. Before you download images, always double-check your Google
Cloud Console’s Billing tab to make sure that you will not go above the
free credit of $200 each month. The price is $7 per 1000 images.
# =========== NO MODIFICATION ZONE STARTS HERE ===============================
# Loop!
#for (i in seq(1,nrow(endp))){
# get_image(endp[i,])
#}
# =========== NO MODIFY ZONE ENDS HERE ========================================
Now, you need to upload the images you downloaded to Google Drive. You should upload the images to the same folder that we used in class - the ‘demo_images’ folder in the root directory of Google Drive. Then, use Google Colab to apply a semantic segmentation model called Pyramid Scene Parsing Network.
Once all of the images are processed and saved in your Google Drive as a CSV file, download the CSV file and merge it back to edges.
# Read the downloaded CSV file from Google Drive
pspnet <- read.csv("seg_output.csv")
# =========== NO MODIFICATION ZONE STARTS HERE ===============================
# Join the pspnet object back to endp object using node_id as the join key.
pspnet_nodes <- endp %>% inner_join(pspnet, by="node_id") %>%
select(type, X, Y, node_id, building, sky, tree, road, sidewalk) %>%
mutate(across(c(building, sky, tree, road, sidewalk), function(x) x/(640*640)))
# =========== NO MODIFY ZONE ENDS HERE ========================================
At the beginning of this assignment, you defined one Census Tract as walkable and the other as unwalkable. The key to the following analysis is the comparison between walkable/unwalkable Census Tracts.
You need to create maps of the proportion of building, sky, tree, road, and sidewalk for walkable and unwalkable areas. In total, you will have 10 maps (two Census Tracts times five categories).
Below the maps, provide a brief description of your findings from the maps.
# TASK ////////////////////////////////////////////////////////////////////////
# Create map(s) to visualize the `pspnet_nodes` objects.
# As long as you can deliver the message clearly, you can use any format/package you want.
# //TASK //////////////////////////////////////////////////////////////////////
pspnet_nodeswalkable <- pspnet_nodes %>% filter(node_id<205)
pspnet_nodesnotwalkable <- pspnet_nodes %>% filter(node_id>204)
tm_shape(pspnet_nodeswalkable %>%
mutate(pct_tree = tree/(640*640))) +
tm_dots(col = "pct_tree", style="quantile")
tm_shape(pspnet_nodesnotwalkable %>%
mutate(pct_tree = tree/(640*640))) +
tm_dots(col = "pct_tree", style="quantile")
tm_shape(pspnet_nodeswalkable %>%
mutate(pct_building = building/(640*640))) +
tm_dots(col = "pct_building", style="quantile")
tm_shape(pspnet_nodesnotwalkable %>%
mutate(pct_building = building/(640*640))) +
tm_dots(col = "pct_building", style="quantile")
tm_shape(pspnet_nodeswalkable %>%
mutate(pct_sky = sky/(640*640))) +
tm_dots(col = "sky", style="quantile")
tm_shape(pspnet_nodesnotwalkable %>%
mutate(pct_sky = sky/(640*640))) +
tm_dots(col = "sky", style="quantile")
tm_shape(pspnet_nodeswalkable %>%
mutate(pct_road = road/(640*640))) +
tm_dots(col = "road", style="quantile")
tm_shape(pspnet_nodesnotwalkable %>%
mutate(pct_road = road/(640*640))) +
tm_dots(col = "road", style="quantile")
tm_shape(pspnet_nodeswalkable %>%
mutate(pct_sidewalk = sidewalk/(640*640))) +
tm_dots(col = "sidewalk", style="quantile")
tm_shape(pspnet_nodesnotwalkable %>%
mutate(pct_sidewalk = sidewalk/(640*640))) +
tm_dots(col = "sidewalk", style="quantile")
You need to calculate the mean of the proportion of building, sky, tree, road, and sidewalk for walkable and unwalkable areas. For example, you need to calculate the mean of building category for each of walkable and unwalkable Census Tracts. Then, you need to calculate the mean of sky category for each of walkable and unwalkable Census Tracts. In total, you will have 10 mean values. After the calculation, provide a brief description of your findings.
# TASK ////////////////////////////////////////////////////////////////////////
# Perform the calculation as described above.
# As long as you can deliver the message clearly, you can use any format/package you want.
# //TASK //////////////////////////////////////////////////////////////////////
typeof(pspnet_nodeswalkable)
## [1] "list"
meanofWalkableTree <- mean(pspnet_nodeswalkable$tree)
print(paste0("Walkable Tract Tree Mean:", meanofWalkableTree))
## [1] "Walkable Tract Tree Mean:0.120667449352788"
#meanofWalkableTree
meanofNotWalkableTree <- mean(pspnet_nodesnotwalkable$tree)
print(paste0("Not Walkable Tract Tree Mean:", meanofNotWalkableTree))
## [1] "Not Walkable Tract Tree Mean:0.17964707661783"
#meanofNotWalkableTree
meanofWalkableBuilding <- mean(pspnet_nodeswalkable$building)
#meanofWalkableBuilding
print(paste0("Walkable Tract Building Mean:", meanofWalkableBuilding))
## [1] "Walkable Tract Building Mean:0.261134440104167"
meanofNotWalkableBuilding <- mean(pspnet_nodesnotwalkable$building)
print(paste0("Not Walkable Tract Building Mean:", meanofNotWalkableBuilding))
## [1] "Not Walkable Tract Building Mean:0.0118967948415857"
#meanofNotWalkableBuilding
meanofWalkableSky <- mean(pspnet_nodeswalkable$sky)
#meanofWalkableSky
print(paste0("Walkable Tract Sky Mean:", meanofWalkableSky))
## [1] "Walkable Tract Sky Mean:0.153521178002451"
meanofNotWalkableSky <- mean(pspnet_nodesnotwalkable$sky)
print(paste0("Not Walkable Tract Sky Mean:", meanofNotWalkableSky))
## [1] "Not Walkable Tract Sky Mean:0.274512679821897"
#meanofNotWalkableSky
meanofWalkableRoad <- mean(pspnet_nodeswalkable$road)
print(paste0("Walkable Tract Road Mean:", meanofWalkableRoad))
## [1] "Walkable Tract Road Mean:0.346924175187653"
#meanofWalkableRoad
meanofNotWalkableRoad <- mean(pspnet_nodesnotwalkable$road)
print(paste0("Not Walkable Tract Road Mean:", meanofNotWalkableRoad))
## [1] "Not Walkable Tract Road Mean:0.23971123007603"
#meanofNotWalkableRoad
meanofWalkableSidewalk <- mean(pspnet_nodeswalkable$sidewalk)
print(paste0("Walkable Tract Sidewalk Mean:", meanofWalkableSidewalk))
## [1] "Walkable Tract Sidewalk Mean:0.0570089183134191"
#meanofWalkableSidewalk
meanofNotWalkableSidewalk <- mean(pspnet_nodesnotwalkable$sidewalk)
print(paste0("Not Walkable Tract Sidewalk Mean:", meanofNotWalkableSidewalk))
## [1] "Not Walkable Tract Sidewalk Mean:0.00923461586796247"
#meanofNotWalkableSidewalk
Brief Description: The means for the Buildings and Sidewalk differ the most between the walkable tract of Midtown Atlanta, and the not walkable tract of Chattahoochee Hills GA (Fulton County). The area in square miles for the tracts differs significantly. Even though Chattahoochee Hills has so called new urban neighborhoods like “Serenbe” the population density is not close to a an urban center like Midtown Atlanta.
You need to calculate the mean of the proportion of building, sky, tree, road, and sidewalk for walkable and unwalkable areas. For example, you need to calculate the mean of building category for each of walkable and unwalkable Census Tracts. Then, you need to calculate the mean of sky category for each of walkable and unwalkable Census Tracts. In total, you will have 10 mean values. After the calculation, provide a brief description of your findings.
# TASK ////////////////////////////////////////////////////////////////////////
# Create boxplot(s) using geom_boxplot() function from ggplot2 package.
# You may find the code from mini-assignment 4 useful here.
# //TASK //////////////////////////////////////////////////////////////////////
#pspnet_nodes %>%
# ggplot(aes(building))+
# geom_histogram()
treeWalkablePlot <- pspnet_nodeswalkable %>%
ggplot(aes(x="Walkable",y=tree))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
treeNotWalkablePlot <- pspnet_nodesnotwalkable %>%
ggplot(aes(x="Not Walkable",y=tree))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
treeWalkablePlot + treeNotWalkablePlot
buildingWalkablePlot <- pspnet_nodeswalkable %>%
ggplot(aes(x="Walkable",y=building))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
buildingNotWalkablePlot <- pspnet_nodesnotwalkable %>%
ggplot(aes(x="Not Walkable",y=building))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
buildingWalkablePlot + buildingNotWalkablePlot
skyWalkablePlot <- pspnet_nodeswalkable %>%
ggplot(aes(x="Walkable",y=sky))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
skyNotWalkablePlot <- pspnet_nodesnotwalkable %>%
ggplot(aes(x="Not Walkable",y=sky))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
skyWalkablePlot + skyNotWalkablePlot
roadWalkablePlot <- pspnet_nodeswalkable %>%
ggplot(aes(x="Walkable",y=road))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
roadNotWalkablePlot <- pspnet_nodesnotwalkable %>%
ggplot(aes(x="Not Walkable",y=road))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
roadWalkablePlot + roadNotWalkablePlot
sidewalkWalkablePlot <- pspnet_nodeswalkable %>%
ggplot(aes(x="Walkable",y=sidewalk))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
sidewalkNotWalkablePlot <- pspnet_nodesnotwalkable %>%
ggplot(aes(x="Not Walkable",y=sidewalk))+
geom_boxplot()+
stat_summary(fun=mean, geom="point", shape=20, color="red", size=4)
sidewalkWalkablePlot + sidewalkNotWalkablePlot
#####FINISH