/
places.Rmd
204 lines (173 loc) · 8.93 KB
/
places.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
---
title: "Meaningful Places & Where to Find Them"
output:
distill::distill_article:
toc: true
# description: "Places and pathways"
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo=T)
```
```{r echo=F}
library(tidyverse)
library(ggthemes)
library(ggwordcloud)
library(KernSmooth)
library(leaflet)
library(MASS)
library(RColorBrewer)
library(sp)
library(sf)
library(smoothr)
```
## Overview
Stilesians were asked:
> **If you lived in the New Haven this Fall**: looking back on life in New Haven this Fall (perhaps for the first time!), in which places on and around campus did you end up having meaningful experiences? \
**If you have been remote in the Fall**: Know that you have been missed. Although you have been remote, perhaps some Yale places have been on your mind. Which places on and around campus do you feel most nostalgic for? Have any virtual Yale spaces been meaningful for you?
The resultant data maps the contours of "meaning"---whatever that, incidentally, means---onto our increasingly flexible concept of place. While some of the places that respondents submitted ended up being virtual, many more ended up being physical. The following sections visualize the responses based on these two modes of place.
## New Haven Area
For the physical locations, we can imagine a topographic map which reveals the peaks and valleys of our community's experiences of meaning and nostalgia throughout New Haven. In cartography, contour lines on maps generally indicate the physical elevation of the Earth's surface. But for our data of meaningful places, contour lines can instead indicate those places that many Stilesians have found meaningful. In other words, the peaks insinuated by the contours below reveal "hot spots" of meaning and nostalgia throughout New Haven.
Feel free to skip past the following code chunk.
```{r}
## CODE FOR SETUP
# Get Places data, jitter lat/lon for better visibility in plotting points
t <- "20201227_235052"
data.places.physical <- read.csv(paste0("data/places.physical_" , t, ".csv"))
places <- data.places.physical %>%
mutate(lon.jitter=jitter(lon, factor=2.2)) %>%
mutate(lat.jitter=jitter(lat, factor=2.2))
# Estimate kernel density and create contour lines
# Heavily adapted from https://gis.stackexchange.com/questions/168886/r-how-to-build-heatmap-with-the-leaflet-package
# Bounding box thanks to bboxfinder.com
kde <- kde2d(places$lon, places$lat, n=c(64, 75),
lims=c(-72.99461, -72.88622, 41.294898, 41.344599))
CL <- contourLines(kde$x , kde$y , kde$z, nlevels=13)
# Format contour lines as SpatialPolygon for Leaflet
spgons <- SpatialPolygons(
lapply(1:length(CL), function(i) {
Polygons(list(Polygon(cbind(CL[[i]]$x, CL[[i]]$y))), ID=i)
})
)
# Smooth contour lines
spgons <- smooth(spgons, method="chaikin", refinements=5)
# Compute colors for the level curves (https://rstudio.github.io/leaflet/colors.html)
levels <- sapply(CL, `[[`, "level")
colorpal <- colorNumeric(palette="YlOrRd", domain=c(-max(levels)/2, max(levels)))
```
```{r layout="l-page", fig.cap="Interact with this map! Hover over points to see their name; pan and zoom around. Darker contour lines represent higher intensity."}
## CODE FOR ACTUAL MAP
leaflet(spgons) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
setView(-72.93, 41.3155, 14) %>%
addPolylines(color=colorpal(levels), opacity=1, weight=3) %>%
addCircleMarkers(data=places, lng=~lon.jitter, lat=~lat.jitter, label=~Name,
radius=3, fillOpacity=0.8, fillColor="yellow", # Interior
weight=1, opacity=0.8, color="black") # Exterior
```
Like a topographic map, the map above shows contour lines which guide the eye to points of interest. The more bunched-together the lines, the sharper the incline. The darker the color, the higher the "elevation" in meaning.
Fun notes:
* Extraordinarily large cluster around Ezra Stiles College. (There is also one[1] Morse point.)
* The Stiles Mountain gives way to a high plateau through Sterling Library, Bass, and Cross Campus.
* There is also a noteworthy knob on Old Campus.
* Koffee? and East Rock Park are also so well-loved to merit their own contour lines.
There are also some other clusters which reveal themselves to the eye, even if not the contours:
* Yale Science buildings (buildings on Science Hill)
* Dunham Lab (including the "Math Lounge") and the CEID dynamic duo
* Off-campus residences scattered around the Yale bubble
* Various green spaces, including East Rock, West Rock, Edgerton Park, and Scantlebury Park
* Various forms of dining
## Virtual Realm
For the virtual places, the venerable word cloud lives to see another day. Unlike with the physical data, no virtual places were repeated among the respondents, so the visualization to follow is arranged randomly.
```{r layout="l-page shaded"}
# Get Places data
data.places.virt <- read.csv(paste0("data/places.virt_" , t, ".csv"))
# Rotate and resize each word randomly
set.seed(2021)
places <- data.places.virt %>%
mutate(angle=90 * sample(c(0, 1), n(), replace=T, prob=c(60, 40))) %>%
mutate(size=sample(c(10.4, 10.7, 11, 11.2), n(), replace=T, prob=c(31, 23, 23, 23)))
# Create word cloud
ggplot(places, aes(label=Name, angle=angle, size=size)) +
geom_text_wordcloud_area(eccentricity=0.4, family="Serif") +
theme_tufte()
```
```{r eval=F, echo=F}
# Defunct code since moving to raster maps
library(osmdata)
library(rnaturalearth)
library(tigris) # gives state data
# Code adapted from that seen in Section
nhv_bb <- getbb("New Haven United States")
big_streets <- nhv_bb %>%
opq() %>%
add_osm_feature(key = "highway",
value = c("motorway", "primary", "motorway_link", "primary_link")
) %>%
osmdata_sf()
med_streets <- nhv_bb %>%
opq() %>%
add_osm_feature(key = "highway",
value = c("secondary", "tertiary", "secondary_link", "tertiary_link")
) %>%
osmdata_sf()
small_streets <- nhv_bb %>%
opq() %>%
add_osm_feature(key = "highway",
value = c("residential", "living_street", "unclassified", "service", "footway")
) %>%
osmdata_sf()
states <- states(class = "sf")
ct <- states %>% filter(NAME=="Connecticut")
g <- ggplot(data=p_jitter) +
geom_sf(data=ct) +
geom_sf(data=big_streets$osm_lines, size=.4, alpha=.3, color="black") +
geom_sf(data=med_streets$osm_lines, size=.3, alpha=.5, color="black") +
geom_sf(data=small_streets$osm_lines, size=.2, alpha=.3, color="black") +
geom_density_2d(aes(x=x, y=y), size=0.2, bins=20) + # Sadly, plotly isn't ready for density_2d_filled
geom_point(aes(x=x, y=y), color="yellow", alpha=0.9) + # Use geom_point for nice plotly hovers
lims(x=x.lim, y=y.lim) +
theme(axis.text=element_blank(), axis.ticks=element_blank(), axis.title=element_blank())
```
```{r echo=F, eval=F}
# Defunct code after moving from downloaded raster maps to tiles fetched each time.
library(ggmap)
library(plotly)
# Get Places data
t <- "20201227_235052"
data.places.physical <- readRDS(paste("data/places.physical_" , t, ".rds"))
# Define bounding box for our region of New Haven (will be the default zoom
# level of our visualization), but also define a slightly larger bounding box
# to give some more border in case viewers want to zoom out.
x.lim0 <- c(-72.939, -72.903)
y.lim0 <- c(41.302, 41.332)
x.lim <- x.lim0 + 0.04 * c(-1, 1)
y.lim <- y.lim0 + 0.02 * c(-1, 1)
p_jitter <- data.places.physical %>%
st_crop(xmin=x.lim[1], xmax=x.lim[2], ymin=y.lim[1], ymax=y.lim[2]) %>%
st_jitter(factor=0.001)
p_jitter['lon'] <- map_dbl(p_jitter$geometry, ~.[1])
p_jitter['lat'] <- map_dbl(p_jitter$geometry, ~.[2])
# Get map data
# newhaven_lowres <- get_stamenmap(bbox=c(left=x.lim[1], right=x.lim[2], bottom=y.lim[1], top=y.lim[2]), zoom=15)
# newhaven_medres <- get_stamenmap(bbox=c(left=x.lim[1], right=x.lim[2], bottom=y.lim[1], top=y.lim[2]), zoom=16)
# newhaven <- get_stamenmap(bbox=c(left=x.lim[1], right=x.lim[2], bottom=y.lim[1], top=y.lim[2]), zoom=17)
# saveRDS(newhaven_lowres, "data/newhaven_lowres.rds", compress=F)
# saveRDS(newhaven_medres, "data/newhaven_medres.rds", compress=F)
# saveRDS(newhaven, "data/newhaven.rds", compress=F)
newhaven_lowres <- readRDS("data/newhaven_lowres.rds")
newhaven_medres <- readRDS("data/newhaven_medres.rds")
newhaven <- readRDS("data/newhaven.rds")
g <- ggmap(newhaven_lowres) +
inset_ggmap(newhaven_medres) +
inset_ggmap(newhaven) +
# Sadly, plotly isn't ready for density_2d_filled
geom_density_2d(data=p_jitter, aes(x=lon, y=lat), size=0.4, alpha=0.8, bins=15) +
geom_point(data=p_jitter, aes(x=lon, y=lat, text=Name),
shape=21, fill="yellow", color="black", size=0.8, stroke=0.1, alpha=0.8) +
lims(x=x.lim0, y=y.lim0) +
theme_tufte() +
theme(axis.text=element_blank(), axis.ticks=element_blank(), axis.title=element_blank())
# https://stackoverflow.com/questions/34605919/formatting-mouse-over-labels-in-plotly-when-using-ggplotly
# ggplotly(g, tooltip="text", height=400)
ggplotly(g, tooltip="text")
```