{"$schema":"https://ejfox.com/schema/page-twin@1.json","kind":"blog_post","url":"https://ejfox.com/blog/2021/nypd-ccrb-complaint-clusters","json_url":"https://ejfox.com/blog/2021/nypd-ccrb-complaint-clusters.json","generator":"ejfox.com/json-twin@1","data":{"cacheVersion":"2026-05-13-gear-cards","html":"<h2 class=\"\" id=\"finding-clusters-of-nypd-officers-in-ccrb-complaint-data\">Finding Clusters of NYPD Officers In CCRB Complaint Data</h2>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624505769/Screen_Shot_2021-06-21_at_8.58.50_PM.jpg\" class=\"w-full mx-auto py-4\">\n<h3 class=\"\" id=\"why\">Why?</h3>\n<p class=\"\">Complaints filed against police officers by the public are often the first and only warning sign that a cop might be on a course of escalating violence.</p>\n<p class=\"\">In the deaths of George Floyd and Eric Garner their killers had a documented history of complaints filed against them. Unfortunately nothing was done to disrupt their pattern of abuse, and both cases ended in those officers killing members of the public they had sworn to protect.</p>\n<h4 class=\"\" id=\"george-floyd\">George Floyd</h4>\n<blockquote class=\"md-blockquote\">\n<p class=\"text-zinc-600 dark:text-zinc-400\">Chauvin, who was fired, has said through his attorney that his handling of Floyd’s arrest was a reasonable use of authorized force. But he was the subject of at least <strong class=\"\">22 complaints or internal investigations during his more than 19 years at the department, only one of which resulted in discipline</strong>. These new interviews show not only that he may have used excessive force in the past, but that he had used startlingly similar techniques.\n<a href=\"https://www.mprnews.org/story/2021/02/05/that-could-have-been-me-the-people-derek-chauvin-choked-before-george-floyd\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://www.mprnews.org/story/2021/02/05/that-could-have-been-me-the-people-derek-chauvin-choked-before-george-floyd\">'That could have been me': The people Derek Chauvin choked before George Floyd</a></p>\n</blockquote>\n<p class=\"\">The officer convicted of murdering George Floyd had at least 22 complaints against him. The officer who put Eric Garner in a chokehold and killed him had <a href=\"https://www.scribd.com/document/342591738/D-Pantaleo-Alleged-CCRB-File\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://www.scribd.com/document/342591738/D-Pantaleo-Alleged-CCRB-File\">7 complaints<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M11.635 0C6.633 0 3.139 3.067 3.139 7.459v.06c.008.085.004.169.004.254c0 1.725.438 3.09 1.253 4.057q1.223 1.45 3.21 1.451q1.662 0 2.617-1.008a3.38 3.38 0 0 0 .955-2.412q0-1.44-.926-2.263q-.927-.823-1.979-.823a4.5 4.5 0 0 0-.859.112q-.516.129-.687.129q-.765 0-.764-.924q0-1.552 1.547-2.67q.454-.326.927-.568c.907-.411 1.988-.637 3.198-.637c2.33 0 4.423.61 6.238 1.816l-1.004 1.602l1.893 1.248l2.205-3.303l-.799-.644C17.75.987 14.878 0 11.635 0m5.683 10.682q-1.662 0-2.617 1.007a3.38 3.38 0 0 0-.955 2.413q0 1.44.928 2.263q.926.823 1.976.823q.325 0 .86-.112q.515-.129.687-.129q.765 0 .764.924q0 .332-.072.645c-.849 2.079-3.022 3.267-6.166 3.267c-2.671 0-5.233-.848-7.319-2.408l1.233-1.52l-1.785-1.39L2.25 19.63l.783.703C5.673 22.698 9.114 24 12.723 24q.602-.001 1.172-.05c2.077-.094 4.15-.87 5.61-2.188q2.245-2.026 2.245-5.592q0-2.587-1.223-4.037q-1.221-1.452-3.209-1.451\" class=\"\"></path></svg></a> <a href=\"https://gothamist.com/news/newly-leaked-documents-suggests-cop-who-killed-eric-garner-had-history-of-misconduct\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://gothamist.com/news/newly-leaked-documents-suggests-cop-who-killed-eric-garner-had-history-of-misconduct\">filed against him</a>.</p>\n<h4 class=\"\" id=\"eric-garner\">Eric Garner</h4>\n<blockquote class=\"md-blockquote\">\n<p class=\"text-zinc-600 dark:text-zinc-400\">Before he put Garner in the chokehold, the records show, he had <em class=\"\">seven disciplinary complaints and 14 individual allegations</em> lodged against him. Four of those allegations were substantiated by an independent review board.\n<a href=\"https://archive.thinkprogress.org/daniel-pantaleo-records-75833e6168f3/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://archive.thinkprogress.org/daniel-pantaleo-records-75833e6168f3/\">The disturbing secret history of the NYPD officer who killed Eric Garner</a></p>\n</blockquote>\n<p class=\"\">Of the 14 individual allegations against Garner's killer, 5 are for force: \"hit against inanimate object\", \"physical force\", and a single complaint in 2014 that would foreshadow the behavior that would eventually end the Officer's career: \"Force - Chokehold\".</p>\n<p class=\"\">I am documenting my analysis in detail for a few reasons:</p>\n<ul class=\"list-disc\">\n<li class=\"\">So that other people who may want to perform similar analysis for other Police Departments can understand and recreate my analysis</li>\n<li class=\"\">So that every step is documented, and any mistake <a href=\"https://en.wikipedia.org/wiki/Linus%27s_law\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://en.wikipedia.org/wiki/Linus%27s_law\">can be easily caught and fixed<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M12.09 13.119c-.936 1.932-2.217 4.548-2.853 5.728c-.616 1.074-1.127.931-1.532.029c-1.406-3.321-4.293-9.144-5.651-12.409c-.251-.601-.441-.987-.619-1.139q-.27-.225-1.122-.271q-.314-.034-.313-.159v-.455l.052-.045c.924-.005 5.401 0 5.401 0l.051.045v.434q0 .177-.225.176l-.564.031c-.485.029-.727.164-.727.436c0 .135.053.33.166.601c1.082 2.646 4.818 10.521 4.818 10.521l.136.046l2.411-4.81l-.482-1.067l-1.658-3.264s-.318-.654-.428-.872c-.728-1.443-.712-1.518-1.447-1.617c-.207-.023-.313-.05-.313-.149v-.468l.06-.045h4.292l.113.037v.451c0 .105-.076.15-.227.15l-.308.047c-.792.061-.661.381-.136 1.422l1.582 3.252l1.758-3.504c.293-.64.233-.801.111-.947c-.07-.084-.305-.22-.812-.24l-.201-.021a.23.23 0 0 1-.145-.051a.15.15 0 0 1-.067-.129v-.427l.061-.045c1.247-.008 4.043 0 4.043 0l.059.045v.436c0 .121-.059.178-.193.178c-.646.03-.782.095-1.023.439c-.12.186-.375.589-.646 1.039l-2.301 4.273l-.065.135l2.792 5.712l.17.048l4.396-10.438c.154-.422.129-.722-.064-.895c-.197-.172-.346-.273-.857-.295l-.42-.016a.26.26 0 0 1-.152-.045c-.043-.029-.072-.075-.072-.119v-.436l.059-.045h4.961l.041.045v.437c0 .119-.074.18-.209.18c-.648.03-1.127.18-1.443.421c-.314.255-.557.616-.736 1.067c0 0-4.043 9.258-5.426 12.339c-.525 1.007-1.053.917-1.503-.031c-.571-1.171-1.773-3.786-2.646-5.71z\" class=\"\"></path></svg></a> by the infinite supply of people on the internet who are smarter than me</li>\n<li class=\"\">To maybe inspire people to use computers to investigate the things in the world that are important to them, and share the tools I use to do that</li>\n</ul>\n<h4 class=\"\" id=\"network-visualization-prior-work--inspiration\">Network visualization prior work / inspiration</h4>\n<p class=\"\">You may have seen network analysis like this before.</p>\n<p class=\"\"><a href=\"https://disinformationindex.org/2021/03/anti-vaccine-networks-thrive-on-instagram-despite-recent-policy-shifts/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://disinformationindex.org/2021/03/anti-vaccine-networks-thrive-on-instagram-despite-recent-policy-shifts/\">Jacob Silver used it to look at the spread of anti-vax material</a>.</p>\n<p class=\"\"><a href=\"https://twitter.com/adico11\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://twitter.com/adico11\">Adi Cohen<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M21.543 7.104c.015.211.015.423.015.636c0 6.507-4.954 14.01-14.01 14.01v-.003A13.94 13.94 0 0 1 0 19.539a9.88 9.88 0 0 0 7.287-2.041a4.93 4.93 0 0 1-4.6-3.42a4.9 4.9 0 0 0 2.223-.084A4.926 4.926 0 0 1 .96 9.167v-.062a4.9 4.9 0 0 0 2.235.616A4.93 4.93 0 0 1 1.67 3.148a13.98 13.98 0 0 0 10.15 5.144a4.929 4.929 0 0 1 8.39-4.49a9.9 9.9 0 0 0 3.128-1.196a4.94 4.94 0 0 1-2.165 2.724A9.8 9.8 0 0 0 24 4.555a10 10 0 0 1-2.457 2.549\" class=\"\"></path></svg></a> has pioneered a method of combining Gephi with CrowdTangle to analyze the network of groups and pages sharing links.</p>\n<h4 class=\"\" id=\"provenance\">Provenance</h4>\n<p class=\"\">WNYC/Gothamist received the data in response to a Freedom of Information Law request and provided me an excel file for analysis.</p>\n<h3 class=\"\" id=\"the-dataset\">The Dataset</h3>\n<h4 class=\"\" id=\"differences-from-data-previously-released-by-propublica\">Differences from data previously released by ProPublica</h4>\n<p class=\"\">ProPublica released and covered <a href=\"https://www.propublica.org/article/nypd-civilian-complaint-review-board-editors-note\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://www.propublica.org/article/nypd-civilian-complaint-review-board-editors-note\">similar data</a> in July of 2020.</p>\n<p class=\"\">They chose to only publish data for \"active-duty officers who’ve had at least one allegation against them substantiated by the CCRB\".</p>\n<p class=\"\">The dataset we are working with today contains every complaint and officer, even those with no substantiated allegations.</p>\n<p class=\"\">It also contains officers who were listed as witnesses on complaints, including complaints found as \"unsubstantiated\" or \"unfounded\" by the CCRB.</p>\n<p class=\"\">This makes it a \"noisier\" dataset. In our case this can be an advantage since we are looking to visualize the network of officers.</p>\n<p class=\"\">Being named with another officer on a complaint, even if that complaint is unfounded, is a signal that those officers interacted in a way that was noticed by the public. Being the subject of an unfounded complaint together might even cause officers to form a tighter relationship. Because of that, I will incorporate witness data into our analysis.</p>\n<h4 class=\"\" id=\"nypd-internal-structure-as-it-relates-to-our-data\">NYPD internal structure as it relates to our data</h4>\n<p class=\"\">The NYPD is divided into coverage areas within the 5 boroughs known as precincts. When I lived in Brooklyn, I lived in the 81st Precinct which covers Bed-Stuy.</p>\n<p class=\"\">The NYPD also has a number of units, like the Warrant Squad or Narcotics that span different precincts. An officer might report to a numbered precinct, but their command is Brooklyn Narcotics, and they are interacting with other officers in their unit more than the precinct they work out of. Our data reflects this.</p>\n<h3 class=\"\" id=\"analysis\">Analysis</h3>\n<h4 class=\"\" id=\"overview-exploration--metadata\">Overview exploration / metadata</h4>\n<p class=\"\">The source dataset is an 81.2MB excel file that I received as <code class=\"md-inline-code\">FOIL2021-00167_Dataset.xlsx</code>. It has 3 tabs. The first has some general notes<sup class=\"\"><a href=\"#user-content-fn-1\" id=\"user-content-fnref-1\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\" class=\"text-blue-600 dark:text-blue-400\">1</a></sup> about the dataset.</p>\n<p class=\"\">The first tab has the title of <code class=\"md-inline-code\">OfficerAllegationHistory</code> and has 181,627 entries and 47<sup class=\"\"><a href=\"#user-content-fn-2\" id=\"user-content-fnref-2\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\" class=\"text-blue-600 dark:text-blue-400\">2</a></sup> columns.</p>\n<p class=\"\">The second tab has the title of <code class=\"md-inline-code\">OfficersInvolvedInComplaints</code> and has 239,608 entries and 18<sup class=\"\"><a href=\"#user-content-fn-3\" id=\"user-content-fnref-3\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\" class=\"text-blue-600 dark:text-blue-400\">3</a></sup> columns.</p>\n<h3 class=\"\" id=\"analyzing-our-data-with-datasette--sqlite\">Analyzing our data with Datasette / SQLite</h3>\n<p class=\"\">Once we <a href=\"https://pypi.org/project/csvs-to-sqlite/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://pypi.org/project/csvs-to-sqlite/\">convert our CSV files</a> into SQLite <code class=\"md-inline-code\">.db</code> files we can use <a href=\"https://github.com/simonw/datasette\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://github.com/simonw/datasette\">Datasette<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" class=\"\"></path></svg></a> to get a sense of the data and slice off pieces for further analysis.</p>\n<p class=\"\">The first thing we might want to look at is the top commands that received complaints since 2010.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">select</span><span style=\"color:#CCCAC2\" class=\"\"> [Officer Command At Incident], </span><span style=\"color:#F28779\" class=\"\">count</span><span style=\"color:#CCCAC2\" class=\"\">([Officer Command At Incident]) </span><span style=\"color:#FFAD66\" class=\"\">from</span><span style=\"color:#CCCAC2\" class=\"\"> OfficerAllegationHistory</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">where</span><span style=\"color:#CCCAC2\" class=\"\"> [Incident Date] </span><span style=\"color:#FFAD66\" class=\"\">BETWEEN</span><span style=\"color:#D5FF80\" class=\"\"> '2010-01-01'</span><span style=\"color:#FFAD66\" class=\"\"> AND</span><span style=\"color:#D5FF80\" class=\"\"> '2010-12-31'</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">group by</span><span style=\"color:#CCCAC2\" class=\"\"> [Officer Command At Incident] </span><span style=\"color:#FFAD66\" class=\"\">order by</span><span style=\"color:#F28779\" class=\"\"> count</span><span style=\"color:#CCCAC2\" class=\"\">([Officer Command At Incident]) </span><span style=\"color:#FFAD66\" class=\"\">DESC</span><span style=\"color:#FFAD66\" class=\"\"> LIMIT</span><span style=\"color:#DFBFFF\" class=\"\"> 5</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"select [Officer Command At Incident], count([Officer Command At Incident]) from OfficerAllegationHistory\nwhere [Incident Date] BETWEEN &#x27;2010-01-01&#x27; AND &#x27;2010-12-31&#x27;\ngroup by [Officer Command At Incident] order by count([Officer Command At Incident]) DESC LIMIT 5\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<ul class=\"list-disc\">\n<li class=\"\">075 PCT: 320</li>\n<li class=\"\">046 PCT: 251</li>\n<li class=\"\">047 PCT: 226</li>\n<li class=\"\">120 PCT: 199</li>\n<li class=\"\">BX IRT : 196</li>\n</ul>\n<p class=\"\">Or the top 10 commands whose complaints ended in penalties.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">select</span><span style=\"color:#CCCAC2\" class=\"\"> [Officer Command At Incident], </span><span style=\"color:#F28779\" class=\"\">count</span><span style=\"color:#CCCAC2\" class=\"\">([Officer Command At Incident]) </span><span style=\"color:#FFAD66\" class=\"\">from</span><span style=\"color:#CCCAC2\" class=\"\"> OfficerAllegationHistory</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">where</span><span style=\"color:#CCCAC2\" class=\"\"> [Incident Date] </span><span style=\"color:#FFAD66\" class=\"\">BETWEEN</span><span style=\"color:#D5FF80\" class=\"\"> '2010-01-01'</span><span style=\"color:#FFAD66\" class=\"\"> AND</span><span style=\"color:#D5FF80\" class=\"\"> '2021-12-31'</span><span style=\"color:#FFAD66\" class=\"\">AND</span><span style=\"color:#CCCAC2\" class=\"\"> [CCRB Allegation Disposition] </span><span style=\"color:#F29E74\" class=\"\">=</span><span style=\"color:#D5FF80\" class=\"\"> 'Substantiated (Charges)'</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">group by</span><span style=\"color:#CCCAC2\" class=\"\"> [Officer Command At Incident] </span><span style=\"color:#FFAD66\" class=\"\">order by</span><span style=\"color:#F28779\" class=\"\"> count</span><span style=\"color:#CCCAC2\" class=\"\">([Officer Command At Incident]) </span><span style=\"color:#FFAD66\" class=\"\">DESC</span><span style=\"color:#FFAD66\" class=\"\"> LIMIT</span><span style=\"color:#DFBFFF\" class=\"\"> 5</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"select [Officer Command At Incident], count([Officer Command At Incident]) from OfficerAllegationHistory\nwhere [Incident Date] BETWEEN &#x27;2010-01-01&#x27; AND &#x27;2021-12-31&#x27;AND [CCRB Allegation Disposition] = &#x27;Substantiated (Charges)&#x27;\ngroup by [Officer Command At Incident] order by count([Officer Command At Incident]) DESC LIMIT 5\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<ul class=\"list-disc\">\n<li class=\"\">WARRSEC: 91</li>\n<li class=\"\">PBBX : 84</li>\n<li class=\"\">081 PCT: 71</li>\n<li class=\"\">079 PCT: 70</li>\n<li class=\"\">075 PCT: 68</li>\n</ul>\n<p class=\"\">After using Datasette to get a sense for the shape of our dataset, we can use it to filter out a slice of the data to use to feed into our next tool and begin doing our network analysis.</p>\n<p class=\"\"><a href=\"https://twitter.com/enjalot\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://twitter.com/enjalot\">Ian Johnson<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M21.543 7.104c.015.211.015.423.015.636c0 6.507-4.954 14.01-14.01 14.01v-.003A13.94 13.94 0 0 1 0 19.539a9.88 9.88 0 0 0 7.287-2.041a4.93 4.93 0 0 1-4.6-3.42a4.9 4.9 0 0 0 2.223-.084A4.926 4.926 0 0 1 .96 9.167v-.062a4.9 4.9 0 0 0 2.235.616A4.93 4.93 0 0 1 1.67 3.148a13.98 13.98 0 0 0 10.15 5.144a4.929 4.929 0 0 1 8.39-4.49a9.9 9.9 0 0 0 3.128-1.196a4.94 4.94 0 0 1-2.165 2.724A9.8 9.8 0 0 0 24 4.555a10 10 0 0 1-2.457 2.549\" class=\"\"></path></svg></a> helped me explore the data a bit in Observable as well.</p>\n<p class=\"\">We looked at when officers received complaints. Here each year is split into a bar. We are showing the officers who received the most complaints in the entire dataset.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036139/Screen_Shot_2021-05-26_at_11.56.10_AM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">Or stacking the bars- the darker they are, the more recent the complaints occurred.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036139/Screen_Shot_2021-05-26_at_12.03.47_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">You can also look at the CCRB outcomes and see how rarely cases are substantiated or end in discipline.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036139/Screen_Shot_2021-05-26_at_12.04.11_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">We also looked at which commands received the most complaints across the entire dataset.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036139/Screen_Shot_2021-05-26_at_12.03.54_PM.png\" class=\"w-full mx-auto py-4\">\n<h4 class=\"\" id=\"filtering-out-exonerated-and-unfounded-complaints-for-our-network\">Filtering out \"Exonerated\" and \"Unfounded\" complaints for our network</h4>\n<p class=\"\">To get our network closer to a representation of officers who are receiving complaints for misconduct we want to filter out any of the cases in which the officer was <code class=\"md-inline-code\">Exonerated</code> or the CCRB's disposition was that it was <em class=\"\">Unfounded</em>.</p>\n<p class=\"\">So to get every complaint filed since 2010 that wasn't marked as <code class=\"md-inline-code\">exonerated</code> or <code class=\"md-inline-code\">unfounded</code> we'll write a query like</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">select</span><span style=\"color:#F29E74\" class=\"\"> *</span><span style=\"color:#FFAD66\" class=\"\"> from</span><span style=\"color:#CCCAC2\" class=\"\"> OfficerAllegationHistory</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">where</span><span style=\"color:#CCCAC2\" class=\"\"> ([Incident Date] </span><span style=\"color:#FFAD66\" class=\"\">BETWEEN</span><span style=\"color:#D5FF80\" class=\"\"> '2010-01-01'</span><span style=\"color:#FFAD66\" class=\"\"> AND</span><span style=\"color:#D5FF80\" class=\"\"> '2021-12-31'</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#FFAD66\" class=\"\">AND</span><span style=\"color:#CCCAC2\" class=\"\"> ([CCRB Allegation Disposition] </span><span style=\"color:#FFAD66\" class=\"\">IS</span><span style=\"color:#FFAD66\" class=\"\"> NOT</span><span style=\"color:#D5FF80\" class=\"\"> 'Exonerated'</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">AND</span><span style=\"color:#CCCAC2\" class=\"\"> [CCRB Allegation Disposition] </span><span style=\"color:#FFAD66\" class=\"\">IS</span><span style=\"color:#FFAD66\" class=\"\"> NOT</span><span style=\"color:#D5FF80\" class=\"\"> 'Unfounded'</span><span style=\"color:#CCCAC2\" class=\"\">)</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"select * from OfficerAllegationHistory\nwhere ([Incident Date] BETWEEN &#x27;2010-01-01&#x27; AND &#x27;2021-12-31&#x27;) AND ([CCRB Allegation Disposition] IS NOT &#x27;Exonerated&#x27;\nAND [CCRB Allegation Disposition] IS NOT &#x27;Unfounded&#x27;)\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Which gives us a slightly more manageable <em class=\"\">65,401 rows</em>. We'll save these results off as a .csv for further analysis.</p>\n<p class=\"\">I had to do some funky stuff<sup class=\"\"><a href=\"#user-content-fn-3\" id=\"user-content-fnref-3-2\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\" class=\"text-blue-600 dark:text-blue-400\">3</a></sup> to fix the dates in SQLite, but once I did that, it was easy to filter by the date column.</p>\n<p class=\"\">We can also export new CSVs for all of the incidents since 2010 for a particular precinct:</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">select</span><span style=\"color:#F29E74\" class=\"\"> *</span><span style=\"color:#FFAD66\" class=\"\"> from</span><span style=\"color:#CCCAC2\" class=\"\"> OfficerAllegationHistory</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">where</span><span style=\"color:#CCCAC2\" class=\"\"> [Incident Date] </span><span style=\"color:#FFAD66\" class=\"\">BETWEEN</span><span style=\"color:#D5FF80\" class=\"\"> '2010-01-01'</span><span style=\"color:#FFAD66\" class=\"\"> AND</span><span style=\"color:#D5FF80\" class=\"\"> '2021-12-31'</span><span style=\"color:#FFAD66\" class=\"\"> AND</span><span style=\"color:#CCCAC2\" class=\"\"> [Officer Command At Incident] </span><span style=\"color:#F29E74\" class=\"\">=</span><span style=\"color:#D5FF80\" class=\"\"> '075 PCT'</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"select * from OfficerAllegationHistory\nwhere [Incident Date] BETWEEN &#x27;2010-01-01&#x27; AND &#x27;2021-12-31&#x27; AND [Officer Command At Incident] = &#x27;075 PCT&#x27;\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">These precinct-specific slices are a bit smaller and more manageable for analysis in Observable.</p>\n<p class=\"\">We'll also want to export another CSV with ONLY complaints that were substantiated</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">select</span><span style=\"color:#F29E74\" class=\"\"> *</span><span style=\"color:#FFAD66\" class=\"\"> from</span><span style=\"color:#CCCAC2\" class=\"\"> OfficerAllegationHistory</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">where</span><span style=\"color:#CCCAC2\" class=\"\"> ([Incident Date] </span><span style=\"color:#FFAD66\" class=\"\">BETWEEN</span><span style=\"color:#D5FF80\" class=\"\"> '2010-01-01'</span><span style=\"color:#FFAD66\" class=\"\"> AND</span><span style=\"color:#D5FF80\" class=\"\"> '2021-12-31'</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#FFAD66\" class=\"\">AND</span><span style=\"color:#CCCAC2\" class=\"\"> ([CCRB Allegation Disposition] </span><span style=\"color:#FFAD66\" class=\"\">IS</span><span style=\"color:#D5FF80\" class=\"\"> 'Substantiated (Charges)'</span><span style=\"color:#FFAD66\" class=\"\"> OR</span><span style=\"color:#CCCAC2\" class=\"\"> [CCRB Allegation Disposition] </span><span style=\"color:#FFAD66\" class=\"\">IS</span><span style=\"color:#D5FF80\" class=\"\"> 'Substantiated (Command Discipline A)'</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">OR</span><span style=\"color:#CCCAC2\" class=\"\"> [CCRB Allegation Disposition] </span><span style=\"color:#FFAD66\" class=\"\">IS</span><span style=\"color:#D5FF80\" class=\"\"> 'Substantiated (Command Discipline B)'</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"select * from OfficerAllegationHistory\nwhere ([Incident Date] BETWEEN &#x27;2010-01-01&#x27; AND &#x27;2021-12-31&#x27;) AND ([CCRB Allegation Disposition] IS &#x27;Substantiated (Charges)&#x27; OR [CCRB Allegation Disposition] IS &#x27;Substantiated (Command Discipline A)&#x27;\nOR [CCRB Allegation Disposition] IS &#x27;Substantiated (Command Discipline B)&#x27;\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<h3 class=\"\" id=\"analyzing-our-data-with-neo4j\">Analyzing our data with Neo4J</h3>\n<p class=\"\">I first encountered Neo4J when I was working with Ben Popken on an <a href=\"https://neo4j.com/blog/story-behind-russian-twitter-trolls/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://neo4j.com/blog/story-behind-russian-twitter-trolls/\">NBC News analysis of tweets tied to Senate Intelligence-identified Russian Twitter Bots</a> where Neo4J provided analysts who were crucial to understanding the shape of our data.</p>\n<p class=\"\">It is an incredibly useful tool for generating and analyzing networks, and I was excited to have another dataset that would let me use its considerable power.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624506093/Screen_Shot_2021-05-31_at_12.05.00_PM.jpg\" class=\"w-full mx-auto py-4\">\n<h4 class=\"\" id=\"importing-our-csv-with-cypher\">Importing our CSV with Cypher</h4>\n<p class=\"\">To import our <code class=\"md-inline-code\">.csv</code> into a network of node and relationships in Neo4J, we will use the <a href=\"https://neo4j.com/developer/cypher/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://neo4j.com/developer/cypher/\">Cypher</a> query language, which makes this process really easy and the code is relatively readable and easy to follow.</p>\n<p class=\"\">Special thanks to <a href=\"https://twitter.com/mdavidallen\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://twitter.com/mdavidallen\">David Allen<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M21.543 7.104c.015.211.015.423.015.636c0 6.507-4.954 14.01-14.01 14.01v-.003A13.94 13.94 0 0 1 0 19.539a9.88 9.88 0 0 0 7.287-2.041a4.93 4.93 0 0 1-4.6-3.42a4.9 4.9 0 0 0 2.223-.084A4.926 4.926 0 0 1 .96 9.167v-.062a4.9 4.9 0 0 0 2.235.616A4.93 4.93 0 0 1 1.67 3.148a13.98 13.98 0 0 0 10.15 5.144a4.929 4.929 0 0 1 8.39-4.49a9.9 9.9 0 0 0 3.128-1.196a4.94 4.94 0 0 1-2.165 2.724A9.8 9.8 0 0 0 24 4.555a10 10 0 0 1-2.457 2.549\" class=\"\"></path></svg></a> at Neo4J for his guidance in writing queries and designing these relationships.</p>\n<p class=\"\">Basically we take the CSV files we exported from Datasette (when we filtered our Exonerated, Unfounded, and everything before 2010) and go through every row and push it into our network.</p>\n<h5 class=\"\" id=\"creating-officer-nodes\">Creating officer nodes</h5>\n<p class=\"\">First we tell Neo4J to use officer.id as a unique constraint (this makes things faster, I think?) and create a node for each officer from one CSV.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">CREATE</span><span style=\"color:#FFAD66\" class=\"\"> CONSTRAINT</span><span style=\"color:#CCCAC2\" class=\"\"> officerIdConstraint </span><span style=\"color:#FFAD66\" class=\"\">ON</span><span style=\"color:#CCCAC2\" class=\"\"> (officer:Officer) ASSERT </span><span style=\"color:#95E6CB\" class=\"\">officer</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">id</span><span style=\"color:#FFAD66\" class=\"\"> IS</span><span style=\"color:#FFAD66\" class=\"\"> UNIQUE</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"CREATE CONSTRAINT officerIdConstraint ON (officer:Officer) ASSERT officer.id IS UNIQUE\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Then I loop through every line of the .csv and create a new Officer node for every new officer I see. I use <code class=\"md-inline-code\">MERGE</code> instead of <code class=\"md-inline-code\">CREATE</code> to make sure I don't duplicate officer nodes.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">LOAD</span><span style=\"color:#CCCAC2\" class=\"\"> CSV </span><span style=\"color:#FFAD66\" class=\"\">WITH</span><span style=\"color:#CCCAC2\" class=\"\"> HEADERS </span><span style=\"color:#FFAD66\" class=\"\">FROM</span><span style=\"color:#D5FF80\" class=\"\"> \"http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficersInvolvedInComplaints_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv\"</span><span style=\"color:#FFAD66\" class=\"\"> AS</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MERGE</span><span style=\"color:#CCCAC2\" class=\"\"> (officer:Officer {id: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Unique Officer Id`</span><span style=\"color:#CCCAC2\" class=\"\">, lastName: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Officer Last Name`</span><span style=\"color:#CCCAC2\" class=\"\">, firstName: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Officer First Name`</span><span style=\"color:#CCCAC2\" class=\"\">, OfficersInvolvedInComplaints: true})</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">RETURN</span><span style=\"color:#CCCAC2\" class=\"\"> officer</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"LOAD CSV WITH HEADERS FROM &#x22;http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficersInvolvedInComplaints_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv&#x22; AS csvLine\nMERGE (officer:Officer {id: csvLine.&#x60;Unique Officer Id&#x60;, lastName: csvLine.&#x60;Officer Last Name&#x60;, firstName: csvLine.&#x60;Officer First Name&#x60;, OfficersInvolvedInComplaints: true})\nRETURN officer\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">This creates <em class=\"\">29,915</em> unique officer nodes.</p>\n<p class=\"\">Then we bind more data into it from our other CSV</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">LOAD</span><span style=\"color:#CCCAC2\" class=\"\"> CSV </span><span style=\"color:#FFAD66\" class=\"\">WITH</span><span style=\"color:#CCCAC2\" class=\"\"> HEADERS </span><span style=\"color:#FFAD66\" class=\"\">FROM</span><span style=\"color:#D5FF80\" class=\"\"> \"http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficerAllegationHistory.csv\"</span><span style=\"color:#FFAD66\" class=\"\"> AS</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MERGE</span><span style=\"color:#CCCAC2\" class=\"\"> (officer:Officer {id: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Unique Officer Id`</span><span style=\"color:#CCCAC2\" class=\"\">, lastName: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Officer Last Name`</span><span style=\"color:#CCCAC2\" class=\"\">, firstName: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Officer First Name`</span><span style=\"color:#CCCAC2\" class=\"\">, shieldNo: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Shield No`</span><span style=\"color:#CCCAC2\" class=\"\">, currentRank: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Current Rank`</span><span style=\"color:#CCCAC2\" class=\"\">, currentCommand: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Current Command`</span><span style=\"color:#CCCAC2\" class=\"\">, OfficerAllegationHistory: true})</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">RETURN</span><span style=\"color:#CCCAC2\" class=\"\"> officer</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"LOAD CSV WITH HEADERS FROM &#x22;http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficerAllegationHistory.csv&#x22; AS csvLine\nMERGE (officer:Officer {id: csvLine.&#x60;Unique Officer Id&#x60;, lastName: csvLine.&#x60;Officer Last Name&#x60;, firstName: csvLine.&#x60;Officer First Name&#x60;, shieldNo: csvLine.&#x60;Shield No&#x60;, currentRank: csvLine.&#x60;Current Rank&#x60;, currentCommand: csvLine.&#x60;Current Command&#x60;, OfficerAllegationHistory: true})\nRETURN officer\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Now we have <em class=\"\">113,265</em> unique officer nodes.</p>\n<p class=\"\">An officer node looks like this:</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"json\" data-theme=\"\"><code data-language=\"json\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#CCCAC2\" class=\"\">{</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#5CCFE6\" class=\"\">  \"identity\"</span><span style=\"color:#CCCAC2B3\" class=\"\">:</span><span style=\"color:#DFBFFF\" class=\"\"> 00001</span><span style=\"color:#CCCAC2B3\" class=\"\">,</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#5CCFE6\" class=\"\">  \"properties\"</span><span style=\"color:#CCCAC2B3\" class=\"\">:</span><span style=\"color:#CCCAC2\" class=\"\"> {</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#5CCFE6\" class=\"\">    \"currentRank\"</span><span style=\"color:#CCCAC2B3\" class=\"\">:</span><span style=\"color:#D5FF80\" class=\"\"> \"Police Officer\"</span><span style=\"color:#CCCAC2B3\" class=\"\">,</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#5CCFE6\" class=\"\">    \"currentCommand\"</span><span style=\"color:#CCCAC2B3\" class=\"\">:</span><span style=\"color:#D5FF80\" class=\"\"> \"81\"</span><span style=\"color:#CCCAC2B3\" class=\"\">,</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#5CCFE6\" class=\"\">    \"lastName\"</span><span style=\"color:#CCCAC2B3\" class=\"\">:</span><span style=\"color:#D5FF80\" class=\"\"> \"Smith\"</span><span style=\"color:#CCCAC2B3\" class=\"\">,</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#5CCFE6\" class=\"\">    \"firstName\"</span><span style=\"color:#CCCAC2B3\" class=\"\">:</span><span style=\"color:#D5FF80\" class=\"\"> \"John\"</span><span style=\"color:#CCCAC2B3\" class=\"\">,</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#5CCFE6\" class=\"\">    \"shieldNo\"</span><span style=\"color:#CCCAC2B3\" class=\"\">:</span><span style=\"color:#D5FF80\" class=\"\"> \"00001\"</span><span style=\"color:#CCCAC2B3\" class=\"\">,</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#5CCFE6\" class=\"\">    \"id\"</span><span style=\"color:#CCCAC2B3\" class=\"\">:</span><span style=\"color:#D5FF80\" class=\"\"> \"000001\"</span><span style=\"color:#CCCAC2B3\" class=\"\">,</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#5CCFE6\" class=\"\">    \"OfficerAllegationHistory\"</span><span style=\"color:#CCCAC2B3\" class=\"\">:</span><span style=\"color:#DFBFFF\" class=\"\"> true</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#CCCAC2\" class=\"\">  }</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#CCCAC2\" class=\"\">}</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"{\n  &#x22;identity&#x22;: 00001,\n  &#x22;properties&#x22;: {\n    &#x22;currentRank&#x22;: &#x22;Police Officer&#x22;,\n    &#x22;currentCommand&#x22;: &#x22;81&#x22;,\n    &#x22;lastName&#x22;: &#x22;Smith&#x22;,\n    &#x22;firstName&#x22;: &#x22;John&#x22;,\n    &#x22;shieldNo&#x22;: &#x22;00001&#x22;,\n    &#x22;id&#x22;: &#x22;000001&#x22;,\n    &#x22;OfficerAllegationHistory&#x22;: true\n  }\n}\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Finally, we need to add a boolean to denote if an officer has ever had a charge substantiated. We'll use this later to please some lawyers. You'll see.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">LOAD</span><span style=\"color:#CCCAC2\" class=\"\"> CSV </span><span style=\"color:#FFAD66\" class=\"\">WITH</span><span style=\"color:#CCCAC2\" class=\"\"> HEADERS </span><span style=\"color:#FFAD66\" class=\"\">FROM</span><span style=\"color:#D5FF80\" class=\"\"> \"http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficerAllegationHistory_FILTERED-SINCE2010-SUBSTANTIATED.csv\"</span><span style=\"color:#FFAD66\" class=\"\"> AS</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MERGE</span><span style=\"color:#CCCAC2\" class=\"\"> (officer:Officer {id: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Unique Officer Id`</span><span style=\"color:#CCCAC2\" class=\"\">})</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">SET</span><span style=\"color:#95E6CB\" class=\"\"> officer</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">ccrbSubstantiatedBool</span><span style=\"color:#F29E74\" class=\"\"> =</span><span style=\"color:#D5FF80\" class=\"\"> \"true\"</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">RETURN</span><span style=\"color:#CCCAC2\" class=\"\"> officer</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"LOAD CSV WITH HEADERS FROM &#x22;http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficerAllegationHistory_FILTERED-SINCE2010-SUBSTANTIATED.csv&#x22; AS csvLine\nMERGE (officer:Officer {id: csvLine.&#x60;Unique Officer Id&#x60;})\nSET officer.ccrbSubstantiatedBool = &#x22;true&#x22;\nRETURN officer\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Now we've marked <em class=\"\">4,768</em> of New York's ~36,000 (13%) finest as having a substantiated complaint in the last 10 years.</p>\n<p class=\"\">Let's NOT do the same thing for OfficersInvolved - because that file contains officers who were merely witnesses to substantiated complaints, and we don't want to accidentally label a witness to a substantiated case.</p>\n<h4 class=\"\" id=\"creating-officer-labels\">Creating officer labels</h4>\n<p class=\"\">Now we need to set labels for our nodes depending on whether they have ever had a complaint substantiated. We don't want to label nodes with names for any officers who may have complaints but have never had any substantiated. I have been told that lawyers think this is a good idea.</p>\n<p class=\"\">First we set every officer label to their unique ID</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#CCCAC2\" class=\"\"> (o:Officer)</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">SET</span><span style=\"color:#95E6CB\" class=\"\"> o</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">label</span><span style=\"color:#F29E74\" class=\"\"> =</span><span style=\"color:#95E6CB\" class=\"\"> o</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">id</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"MATCH (o:Officer)\nSET o.label = o.id\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Then we look for officers with substantiated complaints and set their label to their full name.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#CCCAC2\" class=\"\"> (o:Officer {ccrbSubstantiatedBool: </span><span style=\"color:#D5FF80\" class=\"\">\"true\"</span><span style=\"color:#CCCAC2\" class=\"\">})</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">SET</span><span style=\"color:#95E6CB\" class=\"\"> o</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">label</span><span style=\"color:#F29E74\" class=\"\"> =</span><span style=\"color:#F28779\" class=\"\"> COALESCE</span><span style=\"color:#CCCAC2\" class=\"\">(</span><span style=\"color:#95E6CB\" class=\"\">o</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">firstName</span><span style=\"color:#CCCAC2\" class=\"\"> ,</span><span style=\"color:#D5FF80\" class=\"\">\"\"</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#F29E74\" class=\"\">+</span><span style=\"color:#D5FF80\" class=\"\"> ' '</span><span style=\"color:#F29E74\" class=\"\"> +</span><span style=\"color:#F28779\" class=\"\"> COALESCE</span><span style=\"color:#CCCAC2\" class=\"\">(</span><span style=\"color:#95E6CB\" class=\"\">o</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">lastName</span><span style=\"color:#CCCAC2\" class=\"\"> ,</span><span style=\"color:#D5FF80\" class=\"\">\"\"</span><span style=\"color:#CCCAC2\" class=\"\">)</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"MATCH (o:Officer {ccrbSubstantiatedBool: &#x22;true&#x22;})\nSET o.label = COALESCE(o.firstName ,&#x22;&#x22;) + &#x27; &#x27; + COALESCE(o.lastName ,&#x22;&#x22;)\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Now we have our officers created, we need to create our incidents.</p>\n<h5 class=\"\" id=\"creating-incident-nodes\">Creating incident nodes</h5>\n<p class=\"\">We are going to continue to use our CSV which <em class=\"\">filtered out</em> incidents <em class=\"\">before 2010</em> or that were <em class=\"\">unfounded or exonerated</em>.</p>\n<p class=\"\">First we tell Neo4J that we have unique incident IDs</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">CREATE</span><span style=\"color:#FFAD66\" class=\"\"> CONSTRAINT</span><span style=\"color:#CCCAC2\" class=\"\"> incidentIdConstraint </span><span style=\"color:#FFAD66\" class=\"\">ON</span><span style=\"color:#CCCAC2\" class=\"\"> (incident:Incident) ASSERT </span><span style=\"color:#95E6CB\" class=\"\">incident</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">id</span><span style=\"color:#FFAD66\" class=\"\"> IS</span><span style=\"color:#FFAD66\" class=\"\"> UNIQUE</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"CREATE CONSTRAINT incidentIdConstraint ON (incident:Incident) ASSERT incident.id IS UNIQUE\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Then we create an incident for every row we see in OfficerAllegationHistory. We'll make note of the precinct the incident occurred in, what the specific allegation was, and what date the incident occurred.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">LOAD</span><span style=\"color:#CCCAC2\" class=\"\"> CSV </span><span style=\"color:#FFAD66\" class=\"\">WITH</span><span style=\"color:#CCCAC2\" class=\"\"> HEADERS </span><span style=\"color:#FFAD66\" class=\"\">FROM</span><span style=\"color:#D5FF80\" class=\"\"> \"http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficerAllegationHistory_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv\"</span><span style=\"color:#FFAD66\" class=\"\"> AS</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MERGE</span><span style=\"color:#CCCAC2\" class=\"\"> (incident:Incident {id: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Complaint Id`</span><span style=\"color:#CCCAC2\" class=\"\">})</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">SET</span><span style=\"color:#95E6CB\" class=\"\"> incident</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">incidentPct</span><span style=\"color:#F29E74\" class=\"\"> =</span><span style=\"color:#F28779\" class=\"\"> COALESCE</span><span style=\"color:#CCCAC2\" class=\"\">(csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Precinct Of Incident Occurrence`</span><span style=\"color:#CCCAC2\" class=\"\">,</span><span style=\"color:#D5FF80\" class=\"\">\"N/A\"</span><span style=\"color:#CCCAC2\" class=\"\">)</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">SET</span><span style=\"color:#95E6CB\" class=\"\"> incident</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">ccrbDisposition</span><span style=\"color:#F29E74\" class=\"\"> =</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`CCRB Allegation Disposition`</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">SET</span><span style=\"color:#95E6CB\" class=\"\"> incident</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">allegation</span><span style=\"color:#F29E74\" class=\"\"> =</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Allegation`</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">set</span><span style=\"color:#95E6CB\" class=\"\"> incident</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">date</span><span style=\"color:#F29E74\" class=\"\"> =</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Incident Date`</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">RETURN</span><span style=\"color:#CCCAC2\" class=\"\"> incident</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"LOAD CSV WITH HEADERS FROM &#x22;http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficerAllegationHistory_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv&#x22; AS csvLine\nMERGE (incident:Incident {id: csvLine.&#x60;Complaint Id&#x60;})\nSET incident.incidentPct = COALESCE(csvLine.&#x60;Precinct Of Incident Occurrence&#x60;,&#x22;N/A&#x22;)\nSET incident.ccrbDisposition = csvLine.&#x60;CCRB Allegation Disposition&#x60;\nSET incident.allegation = csvLine.&#x60;Allegation&#x60;\nset incident.date = csvLine.&#x60;Incident Date&#x60;\nRETURN incident\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Now let's do the same for <em class=\"\">OfficersInvolvedInComplaints</em>.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">LOAD</span><span style=\"color:#CCCAC2\" class=\"\"> CSV </span><span style=\"color:#FFAD66\" class=\"\">WITH</span><span style=\"color:#CCCAC2\" class=\"\"> HEADERS </span><span style=\"color:#FFAD66\" class=\"\">FROM</span><span style=\"color:#D5FF80\" class=\"\"> \"http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficersInvolvedInComplaints_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv\"</span><span style=\"color:#FFAD66\" class=\"\"> AS</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MERGE</span><span style=\"color:#CCCAC2\" class=\"\"> (incident:Incident {id: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Complaint Id`</span><span style=\"color:#CCCAC2\" class=\"\">})</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">SET</span><span style=\"color:#95E6CB\" class=\"\"> incident</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">ccrbDisposition</span><span style=\"color:#F29E74\" class=\"\"> =</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Complaint Disposition`</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">RETURN</span><span style=\"color:#CCCAC2\" class=\"\"> incident</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"LOAD CSV WITH HEADERS FROM &#x22;http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficersInvolvedInComplaints_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv&#x22; AS csvLine\nMERGE (incident:Incident {id: csvLine.&#x60;Complaint Id&#x60;})\nSET incident.ccrbDisposition = csvLine.&#x60;Complaint Disposition&#x60;\nRETURN incident\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Now let's create labels for our incidents, which is going to be the allegation.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#CCCAC2\" class=\"\"> (i:Incident)</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">SET</span><span style=\"color:#95E6CB\" class=\"\"> i</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">label</span><span style=\"color:#F29E74\" class=\"\"> =</span><span style=\"color:#95E6CB\" class=\"\"> i</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">allegation</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"MATCH (i:Incident)\nSET i.label = i.allegation\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Now that we have our <em class=\"\">Incidents</em> and our <em class=\"\">Officers</em> we need to create our relationships between them.</p>\n<h4 class=\"\" id=\"creating-relationships-between-incidents-and-officers\">Creating relationships between incidents and officers</h4>\n<p class=\"\">Now for the fun part.</p>\n<p class=\"\">We are going to create a new relationship called <code class=\"md-inline-code\">INVOLVED_IN</code>, and officers can be <code class=\"md-inline-code\">INVOLVED_IN</code> one or many incidents. Incidents may have one or many officers that were <code class=\"md-inline-code\">INVOLVED_IN</code> it, either as witness or subject officers.</p>\n<p class=\"\">First we create our relationships from <em class=\"\">OfficersInvolved</em>:</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">LOAD</span><span style=\"color:#CCCAC2\" class=\"\"> CSV </span><span style=\"color:#FFAD66\" class=\"\">WITH</span><span style=\"color:#CCCAC2\" class=\"\"> HEADERS </span><span style=\"color:#FFAD66\" class=\"\">FROM</span><span style=\"color:#D5FF80\" class=\"\"> \"http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficersInvolvedInComplaints_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv\"</span><span style=\"color:#FFAD66\" class=\"\"> AS</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#CCCAC2\" class=\"\"> (officer:Officer {id: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Unique Officer Id`</span><span style=\"color:#CCCAC2\" class=\"\">}) </span><span style=\"color:#FFAD66\" class=\"\">with</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine, officer</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#CCCAC2\" class=\"\"> (incident:Incident {id: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Complaint Id`</span><span style=\"color:#CCCAC2\" class=\"\">}) </span><span style=\"color:#FFAD66\" class=\"\">with</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine, officer, incident</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">CREATE</span><span style=\"color:#CCCAC2\" class=\"\"> (officer)</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">[:INVOLVED_IN {status: csvLine.`Officer Status`}]</span><span style=\"color:#F29E74\" class=\"\">-></span><span style=\"color:#CCCAC2\" class=\"\">(incident)</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"LOAD CSV WITH HEADERS FROM &#x22;http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficersInvolvedInComplaints_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv&#x22; AS csvLine\nMATCH (officer:Officer {id: csvLine.&#x60;Unique Officer Id&#x60;}) with csvLine, officer\nMATCH (incident:Incident {id: csvLine.&#x60;Complaint Id&#x60;}) with csvLine, officer, incident\nCREATE (officer)-[:INVOLVED_IN {status: csvLine.&#x60;Officer Status&#x60;}]->(incident)\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">Which creates <em class=\"\">94,323</em> relationships.</p>\n<p class=\"\">Then from <em class=\"\">OfficerAllegationHistory</em>:</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">LOAD</span><span style=\"color:#CCCAC2\" class=\"\"> CSV </span><span style=\"color:#FFAD66\" class=\"\">WITH</span><span style=\"color:#CCCAC2\" class=\"\"> HEADERS </span><span style=\"color:#FFAD66\" class=\"\">FROM</span><span style=\"color:#D5FF80\" class=\"\"> \"http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficerAllegationHistory_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv\"</span><span style=\"color:#FFAD66\" class=\"\"> AS</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#CCCAC2\" class=\"\"> (officer:Officer {id: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Unique Officer Id`</span><span style=\"color:#CCCAC2\" class=\"\">}) </span><span style=\"color:#FFAD66\" class=\"\">with</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine, officer</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#CCCAC2\" class=\"\"> (incident:Incident {id: csvLine.</span><span style=\"color:#D5FF80\" class=\"\">`Complaint Id`</span><span style=\"color:#CCCAC2\" class=\"\">}) </span><span style=\"color:#FFAD66\" class=\"\">with</span><span style=\"color:#CCCAC2\" class=\"\"> csvLine, officer, incident</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">CREATE</span><span style=\"color:#CCCAC2\" class=\"\"> (officer)</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">[:INVOLVED_IN {allegation: csvLine.`Allegation`, type: csvLine.`FADO Type`}]</span><span style=\"color:#F29E74\" class=\"\">-></span><span style=\"color:#CCCAC2\" class=\"\">(incident)</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"LOAD CSV WITH HEADERS FROM &#x22;http://localhost:11001/project-185bb75c-b944-451a-9c0f-aeba860ae68a/OfficerAllegationHistory_FILTERED-SINCE2010-NOT-UNFOUNDED-EXONERATED.csv&#x22; AS csvLine\nMATCH (officer:Officer {id: csvLine.&#x60;Unique Officer Id&#x60;}) with csvLine, officer\nMATCH (incident:Incident {id: csvLine.&#x60;Complaint Id&#x60;}) with csvLine, officer, incident\nCREATE (officer)-[:INVOLVED_IN {allegation: csvLine.&#x60;Allegation&#x60;, type: csvLine.&#x60;FADO Type&#x60;}]->(incident)\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\"><strong class=\"\">Now we have 159,671 relationships</strong>. Sick.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036165/Screen_Shot_2021-05-29_at_2.28.27_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">Next we can flatten out our graph a little bit and remove incidents if we want.</p>\n<p class=\"\">We will create a new type of relationship that only occurs between two officers called <code class=\"md-inline-code\">CO_OCCURANCE</code> - we will only make one of these between each officer, but the weight of that link will be decided by how many complaints those officers appear together on.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036231/Screen_Shot_2021-05-29_at_3.48.19_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">So officers who appear on 3 complaints together have a <code class=\"md-inline-code\">CO_OCCURANCE</code> relationship with a weight of 3. This allows us to do some weighted degree analysis when we are making our layout, deciding how large to make nodes, and when we are detecting communities.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#CCCAC2\" class=\"\"> (o1:Officer)</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">[:INVOLVED_IN]</span><span style=\"color:#F29E74\" class=\"\">-></span><span style=\"color:#CCCAC2\" class=\"\">(i:Incident)</span><span style=\"color:#F29E74\" class=\"\">&#x3C;-</span><span style=\"color:#CCCAC2\" class=\"\">[:INVOLVED_IN]</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">(o2:Officer) </span><span style=\"color:#FFAD66\" class=\"\">WHERE</span><span style=\"color:#CCCAC2\" class=\"\"> id(o1)</span><span style=\"color:#F29E74\" class=\"\">&#x3C;</span><span style=\"color:#CCCAC2\" class=\"\">id(o2) </span><span style=\"color:#FFAD66\" class=\"\">with</span><span style=\"color:#CCCAC2\" class=\"\"> o1, o2, </span><span style=\"color:#F28779\" class=\"\">count</span><span style=\"color:#CCCAC2\" class=\"\">(i) </span><span style=\"color:#FFAD66\" class=\"\">as</span><span style=\"color:#CCCAC2\" class=\"\"> weightCount </span><span style=\"color:#FFAD66\" class=\"\">CREATE</span><span style=\"color:#CCCAC2\" class=\"\"> (o1)</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">[:CO_OCCURANCE { weight: weightCount }]</span><span style=\"color:#F29E74\" class=\"\">-></span><span style=\"color:#CCCAC2\" class=\"\">(o2)</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"MATCH (o1:Officer)-[:INVOLVED_IN]->(i:Incident)<-[:INVOLVED_IN]-(o2:Officer) WHERE id(o1)<id(o2) with o1, o2, count(i) as weightCount CREATE (o1)-[:CO_OCCURANCE { weight: weightCount }]->(o2)\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<h4 class=\"\" id=\"officers-without-connections\">Officers without connections</h4>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#CCCAC2\" class=\"\"> (o:Officer) </span><span style=\"color:#FFAD66\" class=\"\">WHERE</span><span style=\"color:#FFAD66\" class=\"\"> NOT</span><span style=\"color:#CCCAC2\" class=\"\"> (o)</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">[:CO_OCCURANCE]</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">() </span><span style=\"color:#FFAD66\" class=\"\">RETURN</span><span style=\"color:#F28779\" class=\"\"> count</span><span style=\"color:#CCCAC2\" class=\"\">(o)</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"MATCH (o:Officer) WHERE NOT (o)-[:CO_OCCURANCE]-() RETURN count(o)\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624506696/Screen_Shot_2021-06-13_at_7.16.11_PM.jpg\" class=\"w-full mx-auto py-4\">\n<h4 class=\"\" id=\"eigenvector-analysis-on-our-network\">Eigenvector analysis on our network</h4>\n<p class=\"\">Let's run a standard centrality analysis algorithm called <a href=\"https://neo4j.com/docs/graph-data-science/current/algorithms/eigenvector-centrality/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://neo4j.com/docs/graph-data-science/current/algorithms/eigenvector-centrality/\">\"Eigenvector Centrality\"</a></p>\n<pre class=\"md-pre\"><code class=\"md-inline-code\">CALL gds.alpha.eigenvector.write({\n  nodeProjection: 'Officer',\n  relationshipProjection: 'CO_OCCURANCE',\n  relationshipProperties: 'weight',\n  relationshipWeightProperty: 'weight',\n  writeProperty: 'eigenvector'\n})\nYIELD nodes, iterations, dampingFactor, writeProperty\n</code></pre>\n<p class=\"\">Now every Officer node has an <code class=\"md-inline-code\">eigenvector</code> value that represents its centrality across our entire NYPD-wide network. The larger the value, the more central that node is.</p>\n<h3 class=\"\" id=\"analyzing-our-data-with-gephi\">Analyzing our data with Gephi</h3>\n<p class=\"\">Neo4J is cool for processing and analyzing tons of data, but I want to draw thousands of circles and lines now and start untangling the hairball of our network.</p>\n<p class=\"\">I am going to use Gephi, which I have a love-hate relationship with, but is unrivaled when it comes to network visualization. Plus, I already know how to use it.</p>\n<p class=\"\">We are going to <a href=\"https://neo4j.com/labs/apoc/4.1/export/gephi/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://neo4j.com/labs/apoc/4.1/export/gephi/\">stream our data from Neo4J to Gephi</a> in order to leverage Neo4J's power to handle huge amounts of data (way more than Gephi) but still get to use Gephi's layout algorithms and analysis techniques.</p>\n<h4 class=\"\" id=\"flattened-co-occurance-network\">Flattened co-occurance network</h4>\n<p class=\"\">To get our flattened network, which removed incident nodes:</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#FFAD66\" class=\"\"> path</span><span style=\"color:#F29E74\" class=\"\">=</span><span style=\"color:#CCCAC2\" class=\"\">(o1:Officer)</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">[r:CO_OCCURANCE]</span><span style=\"color:#F29E74\" class=\"\">-></span><span style=\"color:#CCCAC2\" class=\"\">(o2:Officer) </span><span style=\"color:#FFAD66\" class=\"\">WITH</span><span style=\"color:#CCCAC2\" class=\"\"> o1, </span><span style=\"color:#FFAD66\" class=\"\">path</span><span style=\"color:#FFAD66\" class=\"\"> limit</span><span style=\"color:#DFBFFF\" class=\"\"> 125000</span><span style=\"color:#FFAD66\" class=\"\">  with</span><span style=\"color:#CCCAC2\" class=\"\"> o1, collect(</span><span style=\"color:#FFAD66\" class=\"\">path</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#FFAD66\" class=\"\">as</span><span style=\"color:#CCCAC2\" class=\"\"> paths </span><span style=\"color:#FFAD66\" class=\"\">call</span><span style=\"color:#95E6CB\" class=\"\"> apoc</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">gephi</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#FFAD66\" class=\"\">add</span><span style=\"color:#CCCAC2\" class=\"\">(</span><span style=\"color:#FFAD66\" class=\"\">null</span><span style=\"color:#CCCAC2\" class=\"\">,</span><span style=\"color:#D5FF80\" class=\"\">'workspace1'</span><span style=\"color:#CCCAC2\" class=\"\">, paths, </span><span style=\"color:#D5FF80\" class=\"\">'weight'</span><span style=\"color:#CCCAC2\" class=\"\">, ['weight', 'id', 'eigenvector', 'firstName', 'lastName', 'label', 'date', 'currentCommand']) yield nodes, relationships, </span><span style=\"color:#FFAD66\" class=\"\">time</span><span style=\"color:#FFAD66\" class=\"\"> return</span><span style=\"color:#CCCAC2\" class=\"\"> nodes, relationships, </span><span style=\"color:#FFAD66\" class=\"\">time</span><span style=\"color:#FFAD66\" class=\"\"> ORDER  BY</span><span style=\"color:#95E6CB\" class=\"\"> o1</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">eigenvector</span><span style=\"color:#FFAD66\" class=\"\"> DESC</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"MATCH path=(o1:Officer)-[r:CO_OCCURANCE]->(o2:Officer) WITH o1, path limit 125000  with o1, collect(path) as paths call apoc.gephi.add(null,&#x27;workspace1&#x27;, paths, &#x27;weight&#x27;, [&#x27;weight&#x27;, &#x27;id&#x27;, &#x27;eigenvector&#x27;, &#x27;firstName&#x27;, &#x27;lastName&#x27;, &#x27;label&#x27;, &#x27;date&#x27;, &#x27;currentCommand&#x27;]) yield nodes, relationships, time return nodes, relationships, time ORDER  BY o1.eigenvector DESC\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">This streams 100,000 edges and 25,064 nodes into Gephi.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036180/Screen_Shot_2021-05-29_at_3.03.54_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">We'll run the Force Atlas 2 layout algorithm in Gephi to have the nodes arrange themselves into some sort of sense.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036176/Screen_Shot_2021-05-29_at_2.51.20_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">We can use Gephi's modularity algorithm to color by \"community\" within our network, and we'll tweak our layout algorithm to separate things out a bit.</p>\n<p class=\"\">The communities that Gephi detects often mirror real-world precincts. As one might expect, officers appear on complaints with other officers in their precinct because they are working together most often.</p>\n<p class=\"\">I like that the algorithm detects communities that resemble precincts, and it actually gives me confidence that the community detection is working.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036310/Screen_Shot_2021-05-31_at_12.51.58_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">Then we can add some labels and we've made a map of the network of officers who appeared on CCRB complaints together, and there appear to be a number of closely-knit clusters and different communities within our network.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036311/Screen_Shot_2021-05-31_at_12.59.34_PM.png\" class=\"w-full mx-auto py-4\">\n<h4 class=\"\" id=\"precinct-specific-networks-including-incidents-un-flattened-network\">Precinct-specific networks including incidents (un-flattened network)</h4>\n<p class=\"\">Let's put it all together and stream all the officers from a single precinct using only incidents since 2010.</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">MATCH</span><span style=\"color:#FFAD66\" class=\"\"> path</span><span style=\"color:#F29E74\" class=\"\">=</span><span style=\"color:#CCCAC2\" class=\"\">(o1:Officer)</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">[:INVOLVED_IN]</span><span style=\"color:#F29E74\" class=\"\">-></span><span style=\"color:#CCCAC2\" class=\"\">(i:Incident {incidentPct: </span><span style=\"color:#D5FF80\" class=\"\">\"75\"</span><span style=\"color:#CCCAC2\" class=\"\">})</span><span style=\"color:#F29E74\" class=\"\">&#x3C;-</span><span style=\"color:#CCCAC2\" class=\"\">[:INVOLVED_IN]</span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#CCCAC2\" class=\"\">(o2:Officer)</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">where</span><span style=\"color:#95E6CB\" class=\"\"> i</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">date</span><span style=\"color:#FFAD66\" class=\"\"> IS NOT NULL</span><span style=\"color:#FFAD66\" class=\"\"> and</span><span style=\"color:#95E6CB\" class=\"\"> apoc</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">date</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#F28779\" class=\"\">parse</span><span style=\"color:#CCCAC2\" class=\"\">(</span><span style=\"color:#95E6CB\" class=\"\">i</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">date</span><span style=\"color:#CCCAC2\" class=\"\">, </span><span style=\"color:#D5FF80\" class=\"\">\"ms\"</span><span style=\"color:#CCCAC2\" class=\"\">, </span><span style=\"color:#D5FF80\" class=\"\">'YYYY-mm-dd'</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#F29E74\" class=\"\">></span><span style=\"color:#DFBFFF\" class=\"\"> 1262304000000</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\"> WITH</span><span style=\"color:#CCCAC2\" class=\"\"> o1, </span><span style=\"color:#FFAD66\" class=\"\">path</span><span style=\"color:#CCCAC2\" class=\"\">, i </span><span style=\"color:#FFAD66\" class=\"\">limit</span><span style=\"color:#DFBFFF\" class=\"\"> 100000</span><span style=\"color:#FFAD66\" class=\"\">  with</span><span style=\"color:#CCCAC2\" class=\"\"> o1, i, collect(</span><span style=\"color:#FFAD66\" class=\"\">path</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#FFAD66\" class=\"\">as</span><span style=\"color:#CCCAC2\" class=\"\"> paths </span><span style=\"color:#FFAD66\" class=\"\">call</span><span style=\"color:#95E6CB\" class=\"\"> apoc</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">gephi</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#FFAD66\" class=\"\">add</span><span style=\"color:#CCCAC2\" class=\"\">(</span><span style=\"color:#FFAD66\" class=\"\">null</span><span style=\"color:#CCCAC2\" class=\"\">,</span><span style=\"color:#D5FF80\" class=\"\">'workspace1'</span><span style=\"color:#CCCAC2\" class=\"\">, paths, </span><span style=\"color:#D5FF80\" class=\"\">'weight'</span><span style=\"color:#CCCAC2\" class=\"\">, ['weight', 'id', 'eigenvector', 'firstName', 'lastName', 'date']) yield nodes, relationships, </span><span style=\"color:#FFAD66\" class=\"\">time</span><span style=\"color:#FFAD66\" class=\"\"> return</span><span style=\"color:#CCCAC2\" class=\"\"> nodes, relationships, </span><span style=\"color:#FFAD66\" class=\"\">time</span><span style=\"color:#FFAD66\" class=\"\"> ORDER  BY</span><span style=\"color:#95E6CB\" class=\"\"> o1</span><span style=\"color:#CCCAC2\" class=\"\">.</span><span style=\"color:#95E6CB\" class=\"\">eigenvector</span><span style=\"color:#FFAD66\" class=\"\"> DESC</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"MATCH path=(o1:Officer)-[:INVOLVED_IN]->(i:Incident {incidentPct: &#x22;75&#x22;})<-[:INVOLVED_IN]-(o2:Officer)\nwhere i.date IS NOT NULL and apoc.date.parse(i.date, &#x22;ms&#x22;, &#x27;YYYY-mm-dd&#x27;) > 1262304000000\n WITH o1, path, i limit 100000  with o1, i, collect(path) as paths call apoc.gephi.add(null,&#x27;workspace1&#x27;, paths, &#x27;weight&#x27;, [&#x27;weight&#x27;, &#x27;id&#x27;, &#x27;eigenvector&#x27;, &#x27;firstName&#x27;, &#x27;lastName&#x27;, &#x27;date&#x27;]) yield nodes, relationships, time return nodes, relationships, time ORDER  BY o1.eigenvector DESC\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<p class=\"\">We can also make a network that is un-flattened, that is, we can see nodes for both officers as well as incidents. This way, we can see the patterns in the way incidents tie officers together.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036336/Screen_Shot_2021-06-02_at_6.32.45_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">Every blue circle here is an incident, and every red circle is an officer (both filtered by the 75th precinct, since 2010).</p>\n<p class=\"\">Now let's size the circles by their degree (the number of connections they have) and run a layout algorithm.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036346/Screen_Shot_2021-06-02_at_6.53.13_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">Some big nodes start to pop up, like Martinez, Radoncic, and Grieco. What is causing these officers to co-appear on so many different complaints with so many different officers?</p>\n<p class=\"\">When exploring this network, large nodes pop up, and I became naturally curious what the careers of those officers looked like. One of the first ones that jumped out to me was a big node that represented an officer named Nicholas Rios.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036085/Screen_Shot_2021-05-18_at_8.55.24_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">I googled his name, and one of the first results was a harrowing story of a federal civil rights case that named him.</p>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036085/Screen_Shot_2021-05-18_at_8.55.38_PM.png\" class=\"w-full mx-auto py-4\">\n<p class=\"\">In the reporting that George Joseph did for Gothamist/WNYC, he found that a number of large influencers that appear in this network analysis also acted as influencers on the ground.</p>\n<p class=\"\">He looked at another large node in the network, Adnan Radoncic:</p>\n<blockquote class=\"md-blockquote\">\n<p class=\"text-zinc-600 dark:text-zinc-400\">Atunbi asserted that Radoncic was a catalyst for a group assault on the street that day.\n“As soon as he grabbed me, all the officers was hands on,” he said. “It’s like they just followed his lead.”</p>\n</blockquote>\n<h3 class=\"\" id=\"potential-next-steps\">Potential Next Steps</h3>\n<p class=\"\">There are a few different directions for further analysis that I didn't have time for, but may result in interesting findings.</p>\n<ul class=\"list-disc\">\n<li class=\"\">Explorable NYPD-wide network</li>\n<li class=\"\">Looking at protest complaints</li>\n<li class=\"\">Looking at veterans influencing rookies</li>\n<li class=\"\">Looking at the effects of NYPD discipline</li>\n<li class=\"\">Officer career-specific visualization</li>\n<li class=\"\">Analysis of length/outcomes of CCRB investigations</li>\n<li class=\"\">Geographic analysis</li>\n</ul>\n<h3 class=\"\" id=\"flotsam--jetsam\">Flotsam &#x26; Jetsam</h3>\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624505603/Screen_Shot_2021-06-23_at_9.54.21_PM.png\" class=\"w-full mx-auto py-4\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624505843/Screen_Shot_2021-06-21_at_7.12.27_PM.png\" class=\"w-full mx-auto py-4\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036381/Screen_Shot_2021-06-07_at_1.15.54_PM.png\" class=\"w-full mx-auto py-4\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624506217/Screen_Shot_2021-05-29_at_12.37.37_PM.png\" class=\"w-full mx-auto py-4\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036457/Screen_Shot_2021-06-13_at_10.31.55_PM.png\" class=\"w-full mx-auto py-4\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/v1624036455/Screen_Shot_2021-06-13_at_10.33.01_PM.png\" class=\"w-full mx-auto py-4\">\n<h3 class=\"\" id=\"hire-me-to-do-work-like-this\">Hire me to do work like this</h3>\n<p class=\"\">I do freelance data exploration and visualization for clients who aren't evil. If you'd like to hire me to take a look at a dataset for you, just get in touch at <a href=\"mailto:ejfox@ejfox.com\" class=\"text-blue-600 dark:text-blue-400\">ejfox@ejfox.com</a></p>\n<section data-footnotes=\"\" class=\"footnotes mt-8 pt-8 border-t border-zinc-200 dark:border-zinc-800\"><h2 class=\"sr-only\" id=\"footnote-label\">Footnotes</h2>\n<ol class=\"list-decimal\">\n<li id=\"user-content-fn-1\" class=\"\">\n<p class=\"\">The notes say, basically: these are complaints received in or after the year 2000. Cases that are mediated or were attempted to be mediated are excluded. <a href=\"#user-content-fnref-1\" data-footnote-backref=\"\" aria-label=\"Back to reference 1\" class=\"data-footnote-backref text-blue-600 dark:text-blue-400\">↩</a></p>\n</li>\n<li id=\"user-content-fn-2\" class=\"\">\n<p class=\"\">OfficerAllegationHistory columns: </p><pre class=\"md-pre\"><p class=\"\"></p>\n<p class=\"\">1: As Of Date</p>\n<p class=\"\">2: Allegation Record Identity</p>\n<p class=\"\">3: Unique Officer Id</p>\n<p class=\"\">4: Active Per Last Reported Status</p>\n<p class=\"\">5: Last Reported Active Date</p>\n<p class=\"\">6: Officer First Name</p>\n<p class=\"\">7: Officer Last Name</p>\n<p class=\"\">8: Officer Race</p>\n<p class=\"\">9: Officer Gender</p>\n<p class=\"\">10: Current Rank Abbreviation</p>\n<p class=\"\">11: Current Rank</p>\n<p class=\"\">12: Current Command</p>\n<p class=\"\">13: Shield No</p>\n<p class=\"\">14: Complaint Id</p>\n<p class=\"\">15: Incident Date</p>\n<p class=\"\">16: CCRB Received Date</p>\n<p class=\"\">17: Close Date</p>\n<p class=\"\">18: Officer Rank Abbreviation At Incident</p>\n<p class=\"\">19: Officer Rank At Incident</p>\n<p class=\"\">20: Officer Command At Incident</p>\n<p class=\"\">21: Officer Days On Force At Incident</p>\n<p class=\"\">22: Borough Of Incident Occurrence</p>\n<p class=\"\">23: Precinct Of Incident Occurrence</p>\n<p class=\"\">24: Location Type Of Incident</p>\n<p class=\"\">25: Reason for Police Contact</p>\n<p class=\"\">26: Outcome Of Police Encounter</p>\n<p class=\"\">27: Victim Age At Incident</p>\n<p class=\"\">28: Victim Race</p>\n<p class=\"\">29: Victim Gender</p>\n<p class=\"\">30: FADO Type</p>\n<p class=\"\">31: Allegation</p>\n<p class=\"\">32: CCRB Allegation Disposition</p>\n<p class=\"\">33: Board Discipline Recommendation</p>\n<p class=\"\">34: Non-APU Penalty Report Date</p>\n<p class=\"\">35: Officer Is APU</p>\n<p class=\"\">36: APU CCRB Trial Recommended Penalty</p>\n<p class=\"\">37: APU Trial Commissioner Recommended Penalty</p>\n<p class=\"\">38: APU Plea Agreed Penalty</p>\n<p class=\"\">39: APU Case Status</p>\n<p class=\"\">40: APU Closing Date</p>\n<p class=\"\">41: NYPD Allegation Disposition</p>\n<p class=\"\">42: NYPD Officer Penalty</p>\n<p class=\"\">43: Reconsideration Requested</p>\n<p class=\"\">44: Reconsideration Request Withdrawn</p>\n<p class=\"\">45: Reconsideration Request Rejected</p>\n<p class=\"\">46: Reconsideration Occurred</p>\n<p class=\"\">47: Reconsideration Decision Pending</p>\n</pre>\n<p class=\"\">:<sup class=\"\"><a href=\"#user-content-fn-3\" id=\"user-content-fnref-3-3\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\" class=\"text-blue-600 dark:text-blue-400\">3</a></sup> OfficersInvolvedInComplaints columns: </p><pre class=\"md-pre\"><p class=\"\"></p>\n<p class=\"\">1: As Of Date</p>\n<p class=\"\">2: Officer Status</p>\n<p class=\"\">3: Unique Officer Id</p>\n<p class=\"\">4: Active Per Last Reported Status</p>\n<p class=\"\">5: Last Reported Active Date</p>\n<p class=\"\">6: Officer First Name</p>\n<p class=\"\">7: Officer Last Name</p>\n<p class=\"\">8: Officer Race</p>\n<p class=\"\">9: Officer Gender</p>\n<p class=\"\">10: Current Rank Abbreviation</p>\n<p class=\"\">11: Current Rank</p>\n<p class=\"\">12: Current Command</p>\n<p class=\"\">13: Shield No</p>\n<p class=\"\">14: Complaint Id</p>\n<p class=\"\">15: Complaint Disposition</p>\n<p class=\"\">16: Incident Date</p>\n<p class=\"\">17: CCRB Recieved Date</p>\n<p class=\"\">18: Close Date</p>\n</pre>\n<a href=\"#user-content-fnref-2\" data-footnote-backref=\"\" aria-label=\"Back to reference 2\" class=\"data-footnote-backref text-blue-600 dark:text-blue-400\">↩</a>\n</li>\n<li id=\"user-content-fn-3\" class=\"\">\n<p class=\"\">I ran this in the CLI SQLite client to chop up the date string and re-write it in the way SQLite wants it:</p>\n<figure data-rehype-pretty-code-figure=\"\" class=\"\"><pre class=\"md-pre\" style=\"background-color:#09090b;color:#cccac2\" tabindex=\"0\" data-language=\"sql\" data-theme=\"\"><code data-language=\"sql\" data-theme=\"\" style=\"display: grid;\" class=\"md-codeblock\"><span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">update</span><span style=\"color:#CCCAC2\" class=\"\"> OfficerAllegationHistory</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#FFAD66\" class=\"\">set</span><span style=\"color:#CCCAC2\" class=\"\"> [Incident Date] </span><span style=\"color:#F29E74\" class=\"\">=</span><span style=\"color:#CCCAC2\" class=\"\"> substr([Incident Date], </span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#DFBFFF\" class=\"\">4</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#F29E74\" class=\"\">||</span><span style=\"color:#D5FF80\" class=\"\"> '-'</span><span style=\"color:#F29E74\" class=\"\"> ||</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#CCCAC2\" class=\"\">substr(</span><span style=\"color:#D5FF80\" class=\"\">'00'</span><span style=\"color:#F29E74\" class=\"\"> ||</span><span style=\"color:#CCCAC2\" class=\"\"> ([Incident Date] </span><span style=\"color:#F29E74\" class=\"\">+</span><span style=\"color:#DFBFFF\" class=\"\"> 0</span><span style=\"color:#CCCAC2\" class=\"\">), </span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#DFBFFF\" class=\"\">2</span><span style=\"color:#CCCAC2\" class=\"\">, </span><span style=\"color:#DFBFFF\" class=\"\">2</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#F29E74\" class=\"\">||</span><span style=\"color:#D5FF80\" class=\"\"> '-'</span><span style=\"color:#F29E74\" class=\"\"> ||</span></span>\n<span class=\"\" data-line=\"\"><span style=\"color:#CCCAC2\" class=\"\">substr(</span><span style=\"color:#D5FF80\" class=\"\">'00'</span><span style=\"color:#F29E74\" class=\"\"> ||</span><span style=\"color:#CCCAC2\" class=\"\"> (substr([Incident Date], instr([Incident Date], </span><span style=\"color:#D5FF80\" class=\"\">'/'</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#F29E74\" class=\"\">+</span><span style=\"color:#DFBFFF\" class=\"\"> 1</span><span style=\"color:#CCCAC2\" class=\"\">) </span><span style=\"color:#F29E74\" class=\"\">+</span><span style=\"color:#DFBFFF\" class=\"\"> 0</span><span style=\"color:#CCCAC2\" class=\"\">), </span><span style=\"color:#F29E74\" class=\"\">-</span><span style=\"color:#DFBFFF\" class=\"\">2</span><span style=\"color:#CCCAC2\" class=\"\">, </span><span style=\"color:#DFBFFF\" class=\"\">2</span><span style=\"color:#CCCAC2\" class=\"\">);</span></span><button type=\"button\" title=\"Copy code\" aria-label=\"Copy code\" data=\"update OfficerAllegationHistory\nset [Incident Date] = substr([Incident Date], -4) || &#x27;-&#x27; ||\nsubstr(&#x27;00&#x27; || ([Incident Date] + 0), -2, 2) || &#x27;-&#x27; ||\nsubstr(&#x27;00&#x27; || (substr([Incident Date], instr([Incident Date], &#x27;/&#x27;) + 1) + 0), -2, 2);\" class=\"rehype-pretty-copy\" onclick=\"navigator.clipboard.writeText(this.attributes.data.value);this.classList.add(&#x27;rehype-pretty-copied&#x27;);window.setTimeout(() => this.classList.remove(&#x27;rehype-pretty-copied&#x27;), 3000);\"><span class=\"ready\"></span><span class=\"success\"></span></button><style class=\"\">:root {--copy-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath fill='%23adadad' d='M16.187 9.5H12.25a1.75 1.75 0 0 0-1.75 1.75v28.5c0 .967.784 1.75 1.75 1.75h23.5a1.75 1.75 0 0 0 1.75-1.75v-28.5a1.75 1.75 0 0 0-1.75-1.75h-3.937a4.25 4.25 0 0 1-4.063 3h-7.5a4.25 4.25 0 0 1-4.063-3M31.813 7h3.937A4.25 4.25 0 0 1 40 11.25v28.5A4.25 4.25 0 0 1 35.75 44h-23.5A4.25 4.25 0 0 1 8 39.75v-28.5A4.25 4.25 0 0 1 12.25 7h3.937a4.25 4.25 0 0 1 4.063-3h7.5a4.25 4.25 0 0 1 4.063 3M18.5 8.25c0 .966.784 1.75 1.75 1.75h7.5a1.75 1.75 0 1 0 0-3.5h-7.5a1.75 1.75 0 0 0-1.75 1.75'/%3E%3C/svg%3E\");--success-icon: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2366ff85' d='M9 16.17L5.53 12.7a.996.996 0 1 0-1.41 1.41l4.18 4.18c.39.39 1.02.39 1.41 0L20.29 7.71a.996.996 0 1 0-1.41-1.41z'/%3E%3C/svg%3E\");}pre:has(code) {position: relative;}pre button.rehype-pretty-copy {right: 1px;padding: 0;width: 24px;height: 24px;display: flex;margin-top: 2px;margin-right: 8px;position: absolute;border-radius: 25%;backdrop-filter: blur(3px);& span {width: 100%;aspect-ratio: 1 / 1;}& .ready {background-image: var(--copy-icon);}& .success {display: none; background-image: var(--success-icon);}}&.rehype-pretty-copied {& .success {display: block;} & .ready {display: none;}}pre button.rehype-pretty-copy.rehype-pretty-copied {opacity: 1;& .ready { display: none; }& .success { display: block; }}</style></code></pre></figure>\n<a href=\"#user-content-fnref-3\" data-footnote-backref=\"\" aria-label=\"Back to reference 3\" class=\"data-footnote-backref text-blue-600 dark:text-blue-400\">↩</a>\n \n<a href=\"#user-content-fnref-3-2\" data-footnote-backref=\"\" aria-label=\"Back to reference 3-2\" class=\"data-footnote-backref text-blue-600 dark:text-blue-400\">↩<sup class=\"\">2</sup></a>\n \n<a href=\"#user-content-fnref-3-3\" data-footnote-backref=\"\" aria-label=\"Back to reference 3-3\" class=\"data-footnote-backref text-blue-600 dark:text-blue-400\">↩<sup class=\"\">3</sup></a>\n</li>\n</ol>\n</section>","title":"Finding Clusters of NYPD Officers In CCRB Complaint Data","metadata":{"date":"2021-06-11T08:00:17.000Z","type":"words","hidden":false,"inprogress":false,"dek":"In which various tools and methods are explored for analyzing data that describes a network of complaints against NYPD officers (or any other PD with similar public data)","modified":"2024-09-23T16:13:24.000Z","tags":["data","nypd","visualization","network"],"words":3595,"images":0,"imageDetails":{"total":0,"cloudinary":0,"withDimensions":0},"links":16,"codeBlocks":24,"headers":{"h2":1},"toc":[{"text":"Finding Clusters of NYPD Officers In CCRB Complaint Data","slug":"finding-clusters-of-nypd-officers-in-ccrb-complaint-data","level":"h2","children":[{"text":"Why?","slug":"why","level":"h3","children":[]},{"text":"The Dataset","slug":"the-dataset","level":"h3","children":[]},{"text":"Analysis","slug":"analysis","level":"h3","children":[]},{"text":"Analyzing our data with Datasette / SQLite","slug":"analyzing-our-data-with-datasette--sqlite","level":"h3","children":[]},{"text":"Analyzing our data with Neo4J","slug":"analyzing-our-data-with-neo4j","level":"h3","children":[]},{"text":"Analyzing our data with Gephi","slug":"analyzing-our-data-with-gephi","level":"h3","children":[]},{"text":"Potential Next Steps","slug":"potential-next-steps","level":"h3","children":[]},{"text":"Flotsam & Jetsam","slug":"flotsam--jetsam","level":"h3","children":[]},{"text":"Hire me to do work like this","slug":"hire-me-to-do-work-like-this","level":"h3","children":[]}]}]}},"_links":{"self":"https://ejfox.com/blog/2021/nypd-ccrb-complaint-clusters.json","html":"https://ejfox.com/blog/2021/nypd-ccrb-complaint-clusters","index":"/blog.json"}}