Skip to content

Commit 97e4634

Browse files
Merge pull request #47 from ClojureCivitas/initial-workshop-draft
adding workshop article
2 parents 47f1edb + 1f387a4 commit 97e4634

5 files changed

Lines changed: 396 additions & 2 deletions

File tree

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
---
2+
author: [ezmiller]
3+
description: Getting to know our host city for Clojure/conj 2025. We dive into 311 service data to see what's on the minds of Charlotte's citizens and get a taste of our hands-on data analysis workshop.
4+
type: post
5+
date: '2025-08-15'
6+
category: conj
7+
tags: [clay, workflow, conj]
8+
draft: true
9+
format:
10+
html: {title: 'What''s the Buzz in Charlotte? A Pre-Conj Data Dive'}
11+
12+
---
13+
<style></style><style>.printedClojure .sourceCode {
14+
background-color: transparent;
15+
border-style: none;
16+
}
17+
</style><style>.clay-limit-image-width .clay-image {max-width: 100%}
18+
.clay-side-by-side .sourceCode {margin: 0}
19+
.clay-side-by-side {margin: 1em 0}
20+
</style>
21+
<script src="buzz_files/md-default0.js" type="text/javascript"></script><script src="buzz_files/md-default1.js" type="text/javascript"></script><script src="buzz_files/plotly2.js" type="text/javascript"></script>
22+
This November 12th, Clojure enthusiasts will gather in **Charlotte, North Carolina**
23+
for Clojure/conj 2025.
24+
For many of us, it's a cherished yearly tradition of code,
25+
conversations, and that special *"this is my people"* feeling.
26+
27+
::: {.callout-note}
28+
Fun fact: during the Revolutionary War, a British general called Charlotte a "hornet's nest of rebellion"
29+
for its fierce resistance.
30+
That same spirit of passionate engagement seems to live on in the city's civic life today,
31+
on display using the hornet as their city emblem.
32+
:::
33+
34+
In the spirit of exploration that defines our community, let's get to know our host city
35+
before we even arrive.
36+
What can 3 million service requests tell us about the heart of Charlotte?
37+
38+
39+
## A Glimpse into Charlotte's Data
40+
41+
Let's find out by diving into the city's 311 system, which captures the pulse
42+
of city life through non-emergency service requests.
43+
Every pothole report, noise complaint, and fallen tree notification tells a story.
44+
45+
Downloaded from [Charlotte Service Requests](https://data.charlottenc.gov/datasets/charlotte::service-requests-311/explore?location=35.265099%2C-80.810750%2C9.72).
46+
47+
48+
::: {.sourceClojure}
49+
```clojure
50+
(defonce Charlotte-311
51+
(tc/dataset (fs/file (fs/home) "Downloads" "Service_Requests_311.csv")
52+
{:key-fn csk/->kebab-case-keyword}))
53+
```
54+
:::
55+
56+
57+
Let's see what columns we have
58+
59+
60+
::: {.sourceClojure}
61+
```clojure
62+
(tc/column-names Charlotte-311)
63+
```
64+
:::
65+
66+
67+
68+
::: {.printedClojure}
69+
```clojure
70+
(:x
71+
:y
72+
:objectid
73+
:department
74+
:division
75+
:request-no
76+
:fiscal-year
77+
:fiscal-month
78+
:request-type
79+
:received-date
80+
:internal-field-observation
81+
:title
82+
:cmpd-division
83+
:neighborhood-profile-area
84+
:block-no
85+
:street-direction
86+
:street-name
87+
:street-type
88+
:city
89+
:state
90+
:zip-code
91+
:full-address
92+
:x-coord
93+
:y-coord
94+
:latitude
95+
:longitude
96+
:council-district
97+
:global-id
98+
:pid)
99+
100+
```
101+
:::
102+
103+
104+
I wonder what the request types are
105+
106+
107+
::: {.sourceClojure}
108+
```clojure
109+
(tc/group-by Charlotte-311 :request-type)
110+
```
111+
:::
112+
113+
114+
::: {.clay-dataset}
115+
_unnamed [175 3]:
116+
117+
| :name | :group-id | :data |
118+
|---------------------------|----------:|-----------------------------------------------|
119+
| MISSED RECYCLING | 0 | Group: MISSED RECYCLING [56694 29]: |
120+
| CDOT STREET SIGN REP/REPL | 1 | Group: CDOT STREET SIGN REP/REPL [14259 29]: |
121+
| STREET SWEEPING/FLUSHING | 2 | Group: STREET SWEEPING/FLUSHING [10876 29]: |
122+
| NON_RECYCLABLE ITEMS | 3 | Group: NON_RECYCLABLE ITEMS [1542623 29]: |
123+
| HNS HEALTH AND SANITATION | 4 | Group: HNS HEALTH AND SANITATION [147023 29]: |
124+
| CART REPAIR-GARBAGE | 5 | Group: CART REPAIR-GARBAGE [69893 29]: |
125+
| RECYCLABLE ITEMS | 6 | Group: RECYCLABLE ITEMS [366433 29]: |
126+
| SW DOCUMENT RECYCLING | 7 | Group: SW DOCUMENT RECYCLING [32594 29]: |
127+
| PARKING ON LAWN OFFHOURS | 8 | Group: PARKING ON LAWN OFFHOURS [6019 29]: |
128+
| CDOT SIGHT OBSTRUCTION | 9 | Group: CDOT SIGHT OBSTRUCTION [4055 29]: |
129+
| ... | ... | ... |
130+
| NEW SVC BUSINESS GARBAGE | 164 | Group: NEW SVC BUSINESS GARBAGE [225 29]: |
131+
| CURBIT PICKUP DAY INQUIRY | 165 | Group: CURBIT PICKUP DAY INQUIRY [39 29]: |
132+
| ROW OBSTRUCT OTHER | 166 | Group: ROW OBSTRUCT OTHER [1630 29]: |
133+
| SWS MLTFMLY SITE INVSTGT | 167 | Group: SWS MLTFMLY SITE INVSTGT [5 29]: |
134+
| ILLEGAL PARKING | 168 | Group: ILLEGAL PARKING [1211 29]: |
135+
| ZON DUPLEX/DUPLEXES | 169 | Group: ZON DUPLEX/DUPLEXES [68 29]: |
136+
| SUBDIVISIONS | 170 | Group: SUBDIVISIONS [29 29]: |
137+
| UT/WATER QUALITY TESTING | 171 | Group: UT/WATER QUALITY TESTING [1 29]: |
138+
| CART PURCHASE | 172 | Group: CART PURCHASE [8 29]: |
139+
| HOMELESS SUPPORT OUTREACH | 173 | Group: HOMELESS SUPPORT OUTREACH [929 29]: |
140+
| HNS ESCALATED REQUESTS | 174 | Group: HNS ESCALATED REQUESTS [82 29]: |
141+
142+
143+
:::
144+
145+
146+
Let's see what are the most common requests
147+
148+
149+
::: {.sourceClojure}
150+
```clojure
151+
(def frequent-requests
152+
(-> Charlotte-311
153+
(tc/group-by :request-type)
154+
(tc/aggregate {:frequency tc/row-count})
155+
(tc/order-by :frequency :desc)))
156+
```
157+
:::
158+
159+
160+
161+
::: {.sourceClojure}
162+
```clojure
163+
frequent-requests
164+
```
165+
:::
166+
167+
168+
::: {.clay-dataset}
169+
_unnamed [175 2]:
170+
171+
| :$group-name | :frequency |
172+
|---------------------------|-----------:|
173+
| NON_RECYCLABLE ITEMS | 1542623 |
174+
| RECYCLABLE ITEMS | 366433 |
175+
| HNS HEALTH AND SANITATION | 147023 |
176+
| CART REPAIR-GARBAGE | 69893 |
177+
| MISSED RECYCLING | 56694 |
178+
| 311 DOCUMENT | 52972 |
179+
| SW DOCUMENT GARBAGE | 46761 |
180+
| SW DOCUMENT RECYCLING | 32594 |
181+
| DEAD ANIMAL COLLECTION | 30048 |
182+
| SW DOCUMENT YARD WASTE | 26465 |
183+
| ... | ... |
184+
| COVID 19-PRICE GOUGING | 4 |
185+
| SW EXCESSIVE STORM-SW USE | 2 |
186+
| SW REMINDER BULKY-SW USE | 2 |
187+
| SWS MLTFMLY FIELD OBSERVE | 2 |
188+
| ON CALL - SWS SPEC SERV | 1 |
189+
| COMPLEX PROBLEM | 1 |
190+
| UT/LANDSCAPE | 1 |
191+
| DISABILITY ACT | 1 |
192+
| UT/MANDATORY | 1 |
193+
| BUS STOP-REMOVE TRASH CAN | 1 |
194+
| UT/WATER QUALITY TESTING | 1 |
195+
196+
197+
:::
198+
199+
200+
The most frequent request type is about non-recyclable items.
201+
It suggests Charlotte residents care about recycling
202+
but might need clearer guidelines about what can be recycled.
203+
The high volume of requests also shows that people feel comfortable
204+
asking the city for guidance.
205+
Data like this helps cities improve their communication and services.
206+
207+
208+
::: {.sourceClojure}
209+
```clojure
210+
(-> frequent-requests
211+
(plotly/base {:=title "Charlotte 311 Service Requests"})
212+
(plotly/layer-bar {:=x-title "Request Type"
213+
:=y :frequency
214+
:=y-title "Count"}))
215+
```
216+
:::
217+
218+
219+
220+
```{=html}
221+
<div style="height:auto;width:100%;"><script>Plotly.newPlot(document.currentScript.parentElement,
222+
[{"y":[1542623,366433,147023,69893,56694,52972,46761,32594,30048,26465,25145,24900,24268,23914,20396,20359,20121,18946,17301,16702,16495,16012,15404,14337,14259,13106,12496,10876,10659,10616,10461,9922,9117,8710,8601,8286,8255,8243,8128,8057,7749,7528,7266,7264,6936,6355,6249,6019,5467,5301,5124,4967,4879,4431,4355,4055,3939,3836,3723,3559,3480,3248,3200,3003,2957,2823,2700,2663,2592,2592,2518,2392,2321,2187,2175,1874,1643,1630,1598,1440,1431,1365,1335,1325,1248,1211,1136,1045,1043,1001,983,977,971,969,929,870,836,835,816,794,790,785,785,677,564,509,478,476,441,406,368,364,351,331,278,264,250,228,225,219,214,210,208,185,180,151,128,125,113,105,100,89,82,74,68,63,61,60,53,51,43,41,39,37,33,29,28,28,27,22,18,15,15,15,12,11,10,9,9,8,8,6,5,4,4,2,2,2,1,1,1,1,1,1,1],"r":null,"name":"","fill":null,"mode":null,"width":null,"type":"bar","theta":null,"z":null,"lon":null,"lat":null,"text":null}], {"width":500,"height":400,"margin":{"t":25},"automargin":false,"plot_bgcolor":"rgb(235,235,235)","xaxis":{"gridcolor":"rgb(255,255,255)","title":"Request Type","showgrid":true},"yaxis":{"gridcolor":"rgb(255,255,255)","title":"Count","showgrid":true},"title":"Charlotte 311 Service Requests"}, {});</script></div>
223+
```
224+
225+
226+
That's a long tail you have there.
227+
Let's focus on the top 5.
228+
229+
230+
::: {.sourceClojure}
231+
```clojure
232+
(-> frequent-requests
233+
(tc/select-rows (range 5))
234+
(plotly/base {:=title "Charlotte 311 Service Requests"})
235+
(plotly/layer-bar {:=x :$group-name
236+
:=x-title "Request Type"
237+
:=y :frequency
238+
:=y-title "Count"}))
239+
```
240+
:::
241+
242+
243+
244+
```{=html}
245+
<div style="height:auto;width:100%;"><script>Plotly.newPlot(document.currentScript.parentElement,
246+
[{"y":[1542623,366433,147023,69893,56694],"r":null,"name":"","fill":null,"mode":null,"width":null,"type":"bar","theta":null,"z":null,"lon":null,"lat":null,"x":["NON_RECYCLABLE ITEMS","RECYCLABLE ITEMS","HNS HEALTH AND SANITATION","CART REPAIR-GARBAGE","MISSED RECYCLING"],"text":null}], {"width":500,"height":400,"margin":{"t":25},"automargin":false,"plot_bgcolor":"rgb(235,235,235)","xaxis":{"gridcolor":"rgb(255,255,255)","title":"Request Type","showgrid":true},"yaxis":{"gridcolor":"rgb(255,255,255)","title":"Count","showgrid":true},"title":"Charlotte 311 Service Requests"}, {});</script></div>
247+
```
248+
249+
250+
This brief analysis gives us a snapshot of daily life in Charlotte, revealing a community
251+
that's actively engaged in civic life and recycling. It's a perfect backdrop for the
252+
kind of thoughtful problem-solving we cherish in the Clojure community.
253+
254+
![Clean data, clean streets. A city after our own hearts.](buzz.webp)
255+
256+
257+
## Join Us at the Workshop
258+
259+
This journey from a raw CSV file to a clear visualization is exactly what our
260+
**Empowering Data Analysis through SciCloj** [workshop](https://www.2025.clojure-conj.org/workshops) is all about.
261+
Led by me, Ethan Miller, you'll start your Conj experience by diving into practical,
262+
hands-on data analysis and come away with new ideas to carry back home.
263+
264+
**You will learn how to:**
265+
266+
- Load and explore real-world datasets
267+
- Create clear, reproducible analyses
268+
- Share your insights through interactive notebooks
269+
- Leverage Clojure's immutable data structures for data science
270+
271+
We can't wait to explore data with you. See you in Charlotte!
272+
273+
274+
```{=html}
275+
<div style="background-color:grey;height:2px;width:100%;"></div>
276+
```
277+
278+
279+
280+
```{=html}
281+
<div><pre><small><small>source: <a href="https://github.com/ClojureCivitas/clojurecivitas.github.io/blob/main/src/conferences/conj2025/workshop/scicloj/buzz.clj">src/conferences/conj2025/workshop/scicloj/buzz.clj</a></small></small></pre></div>
282+
```

site/db.edn

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
:image "https://avatars.githubusercontent.com/u/36110?v=4"
55
:url "https://chouser.us/"
66
:links [{:icon "github" :href "https://github.com/chouser"}]}
7+
{:id :ezmiller
8+
:name "Ethan Miller"
9+
:image "https://avatars.githubusercontent.com/u/772738?v=4"
10+
:url "https://github.com/ezmiller"
11+
:affiliation [:scicloj]}
712
{:id :daslu
813
:name "Daniel Slutsky"
914
:image "https://avatars.githubusercontent.com/u/5673102?v=4"

0 commit comments

Comments
 (0)