├── data ├── raw │ ├── .gitkeep │ ├── characters_hp.csv │ └── characters_ij.csv ├── processed │ ├── .gitkeep │ └── bookworm.json ├── other-files │ ├── Bookworm, PyData NYC 17.pdf │ └── Bookworm, Databeers London 2018.pdf └── README.md ├── requirements.txt ├── bookworm ├── run_bookworm.py ├── __init__.py ├── visualise.py ├── d3 │ ├── index.html │ └── bookworm.json ├── analyse.py └── build_network.py ├── 07 - Graph Matching and Novel Similarity.ipynb ├── LICENSE.md ├── run_bookworm.py ├── README.md └── 01 - Intro to Bookworm.ipynb /data/raw/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/processed/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pandas 2 | numpy 3 | nltk 4 | spacy 5 | networkx 6 | -------------------------------------------------------------------------------- /data/other-files/Bookworm, PyData NYC 17.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harrisonpim/bookworm/HEAD/data/other-files/Bookworm, PyData NYC 17.pdf -------------------------------------------------------------------------------- /data/other-files/Bookworm, Databeers London 2018.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harrisonpim/bookworm/HEAD/data/other-files/Bookworm, Databeers London 2018.pdf -------------------------------------------------------------------------------- /bookworm/run_bookworm.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from bookworm import * 3 | 4 | if __name__ == '__main__': 5 | parser = argparse.ArgumentParser() 6 | 7 | parser.add_argument('--path', 8 | help='Path to the novel\'s .txt file', 9 | required=True) 10 | 11 | parser.add_argument('--d3', 12 | help='Output a dictionary which is interpretable by ', 13 | action='store_true') 14 | 15 | args = parser.parse_args() 16 | interaction_df = bookworm(args.path) 17 | 18 | if args.d3 is True: 19 | print(d3_dict(interaction_df)) 20 | else: 21 | print(interaction_df) 22 | -------------------------------------------------------------------------------- /data/README.md: -------------------------------------------------------------------------------- 1 | # Data Acquisition 2 | Fundametally, all bookworm needs is a `.txt` file. If you can assemble your own material using material that you already own, go ahead! 3 | - [Project Gutenberg](https://www.gutenberg.org/) is a brilliant resource of freely available, out of copyright textual material, providing room for a lot of exploration of historical literature. Click on a book and download the `Plain Text UTF-8` copy. 4 | - [The British Library / Microsoft OCR project](https://data.bl.uk/digbks/) sought to digitise a significant portion of the Library's historic texts using Optical Character Recognition (OCR) back in 2007. Computer vision was still pretty nascent at that point and the project also stopped short of its intended volume, but there's room for a lot of interesting work to be done there. 5 | -------------------------------------------------------------------------------- /bookworm/__init__.py: -------------------------------------------------------------------------------- 1 | from .build_network import * 2 | from .analyse import * 3 | from .visualise import * 4 | 5 | __all__ = [ 6 | # build_network 7 | 'load_book', 8 | 'load_characters', 9 | 'remove_punctuation', 10 | 'extract_character_names', 11 | 'get_sentence_sequences', 12 | 'get_word_sequences', 13 | 'get_character_sequences', 14 | 'find_connections', 15 | 'calculate_cooccurence', 16 | 'get_interaction_df', 17 | 'bookworm', 18 | # analyse 19 | 'character_density', 20 | 'split_book', 21 | 'chronological_network', 22 | 'select_k', 23 | 'graph_similarity', 24 | 'comparison_df', 25 | # visualise 26 | 'draw_with_communities', 27 | 'd3_dict', 28 | ] 29 | -------------------------------------------------------------------------------- /07 - Graph Matching and Novel Similarity.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Graph Matching and Novel Similarity" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": null, 13 | "metadata": { 14 | "collapsed": true 15 | }, 16 | "outputs": [], 17 | "source": [] 18 | } 19 | ], 20 | "metadata": { 21 | "kernelspec": { 22 | "display_name": "Python [conda root]", 23 | "language": "python", 24 | "name": "conda-root-py" 25 | }, 26 | "language_info": { 27 | "codemirror_mode": { 28 | "name": "ipython", 29 | "version": 3 30 | }, 31 | "file_extension": ".py", 32 | "mimetype": "text/x-python", 33 | "name": "python", 34 | "nbconvert_exporter": "python", 35 | "pygments_lexer": "ipython3", 36 | "version": "3.5.3" 37 | } 38 | }, 39 | "nbformat": 4, 40 | "nbformat_minor": 2 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Harrison Pim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bookworm/visualise.py: -------------------------------------------------------------------------------- 1 | import community 2 | import matplotlib.pyplot as plt 3 | import networkx as nx 4 | 5 | 6 | def draw_with_communities(book): 7 | ''' 8 | draw a book's network with its nodes coloured by (detected) community 9 | 10 | Parameters 11 | ---------- 12 | book : nx.Graph (required) 13 | graph to be analysed and visualised 14 | ''' 15 | partitions = community.best_partition(book) 16 | values = [partitions.get(node) for node in book.nodes()] 17 | 18 | nx.draw(book, 19 | cmap=plt.get_cmap("RdYlBu"), 20 | node_color=values, 21 | with_labels=True) 22 | 23 | 24 | def d3_dict(interaction_df): 25 | ''' 26 | Reformats a DataFrame of interactions into a dictionary which is 27 | interpretable by the Mike Bostock's d3.js force directed graph script 28 | https://bl.ocks.org/mbostock/4062045 29 | 30 | Parameters 31 | ---------- 32 | interaction_df : pandas.DataFrame (required) 33 | DataFrame enumerating the strength of interactions between charcters. 34 | source = character one 35 | target = character two 36 | value = strength of interaction between character one and character two 37 | 38 | Returns 39 | ------- 40 | d3_dict : dict 41 | a dictionary of nodes and links in a format which is immediately 42 | interpretable by the d3.js script 43 | ''' 44 | nodes = [{"id": str(id), "group": 1} for id in set(interaction_df['source'])] 45 | links = interaction_df.to_dict(orient='records') 46 | return {'nodes': nodes, 'links': links} 47 | -------------------------------------------------------------------------------- /run_bookworm.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import json 3 | from bookworm import * 4 | 5 | if __name__ == '__main__': 6 | parser = argparse.ArgumentParser() 7 | 8 | parser.add_argument('--path', 9 | help='Path to the novel\'s .txt file', 10 | required=True) 11 | 12 | parser.add_argument('--output_file', 13 | help='The path+filename where the output will be stored') 14 | 15 | parser.add_argument('--d3', 16 | help=('Output a dictionary which is interpretable by ' 17 | 'the d3.js force directed graph script'), 18 | action='store_true') 19 | 20 | parser.add_argument('--threshold', 21 | help=('Threshold value for interaction inlclusion in ' 22 | 'output interatcion_df'), 23 | default=2) 24 | 25 | args = parser.parse_args() 26 | 27 | interaction_df = bookworm(args.path, threshold=int(args.threshold)) 28 | 29 | if (args.d3 is True) and (args.output_file is None): 30 | with open('bookworm/d3/bookworm.json', 'w') as fp: 31 | json.dump(d3_dict(interaction_df), fp) 32 | elif (args.d3 is True) and (args.output_file is not None): 33 | with open(args.output_file, 'w') as fp: 34 | json.dump(d3_dict(interaction_df), fp) 35 | elif (args.d3 is False) and (args.output_file is not None): 36 | interaction_df.to_csv(args.output_file) 37 | elif (args.d3 is False) and (args.output_file is None): 38 | print(interaction_df) 39 | -------------------------------------------------------------------------------- /data/raw/characters_hp.csv: -------------------------------------------------------------------------------- 1 | Vernon, Dursley 2 | Petunia, Dursley 3 | Dudley, Duddy 4 | Lily 5 | James 6 | Harry, Potter 7 | Voldemort, Lord, You-Know-Who 8 | Jim McGuffin 9 | secretary 10 | Dumbledore, Albus 11 | McGonagall, Minerva 12 | Diggle 13 | Pomfrey, Madam 14 | Hagrid, Rubeus 15 | Sirius 16 | Marge, Aunt 17 | Figg 18 | Tibbles 19 | Snowy 20 | Mr Paws 21 | Tufty 22 | Yvonne 23 | Piers Polkiss 24 | A boa constrictor 25 | Dennis 26 | Malcolm 27 | Gordon 28 | Merlin 29 | Mr Evans 30 | Mrs Evans 31 | Cornelius, Fudge 32 | Miranda Goshawk 33 | Bathilda, Bagshot 34 | Adalbert Waffling 35 | Emeric Switch 36 | Phyllida Spore 37 | Arsenus Jigger 38 | Newton Scamander 39 | Quentin Trimble 40 | Tom 41 | Doris Crockford 42 | Quirrell 43 | Griphook 44 | Madam Malkin 45 | Draco, Malfoy 46 | Lucius, mr. malfoy 47 | Narcissa, mrs. Malfoy 48 | Vindictus Viridian 49 | Hedwig 50 | Ollivander 51 | Ginny 52 | Molly 53 | Percy 54 | Fred 55 | George 56 | Ron, Weasley 57 | Neville, Longbottom 58 | Lee, Jordan 59 | Bill 60 | Charlie 61 | Arthur 62 | Peter, Pettigrew 63 | Cornelius Agrippa 64 | Claudius Ptolemy 65 | Gellert, Grindelwald 66 | Nicolas, Flamel 67 | Morgan le Fay 68 | Hengist of Woodcroft 69 | Alberic Grunnion 70 | Circe 71 | Paracelsus 72 | Cliodna 73 | Bertie Bott 74 | Trevor 75 | Hermione, Granger 76 | Crabbe 77 | Goyle 78 | Hermes 79 | Fat Friar 80 | Peeves 81 | Sorting, Hat 82 | Hannah Abbott 83 | Susan Bones 84 | Terry Boot 85 | Mandy Brocklehurst 86 | Lavender Brown 87 | Millicent Bulstrode 88 | Justin Finch-Fletchley 89 | Seamus Finnigan 90 | Morag MacDougal 91 | Lily Moon 92 | Theodore Nott 93 | Pansy Parkinson 94 | Padma Patil 95 | Parvati Patil 96 | Sally-Anne Perks 97 | Dean, Thomas 98 | Lisa Turpin 99 | Blaise, Zabini 100 | Nearly Headless Nick 101 | Bloody Baron 102 | Algie 103 | Enid 104 | Snape, severus 105 | Filch 106 | Hooch 107 | Fat Lady 108 | Mrs Norris 109 | Sprout 110 | Cuthbert Binns 111 | Emeric the Evil 112 | Uric the Oddball 113 | Flitwick 114 | Fang 115 | Oliver Wood 116 | Helena Ravenclaw 117 | Gregory the Smarmy 118 | Fluffy 119 | Baruffio 120 | Angelina Johnson 121 | Marcus Flint 122 | Alicia Spinnet 123 | Katie Bell 124 | Miles Bletchley 125 | Adrian Pucey 126 | Terence Higgs 127 | Madam Pince 128 | Perenelle Flamel 129 | Norbert 130 | Ronan 131 | Bane 132 | Firenze 133 | Unicorn 134 | Elfric the Eager 135 | Giant Squid -------------------------------------------------------------------------------- /bookworm/d3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 18 | 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bookworm :books: 2 | Most novels are, in some way, a description of a social network. Bookworm ingests novels, builds a solid version of their implicit character network and spits out a intuitively understandable and deeply analysable graph. 3 | 4 | 5 | ### Navigation 6 | - [bookworm](bookworm) for the code itself. 7 | - Notebooks including example usage (with a load of interwoven description of how the thing actually works), in jupyter notebook form. [Start Here](01%20-%20Intro%20to%20Bookworm.ipynb) 8 | - [data](data) for a description of how to get hold of data so that you can run bookworm yourself. 9 | 10 | 11 | ### Usage 12 | #### Command Line Usage 13 | The `bookworm('path/to/book.txt')` function wraps the following steps into one simple command, allowing the entire analysis process to be run easily from the command line 14 | ```bash 15 | python run_bookworm.py --path 'path/to/book.txt' 16 | ``` 17 | - Add `--d3` to format the output for interpretation by the d3.js force directed graph 18 | - Add `--threshold n` where n is an integer to specify the minimum character interaction strength to be included in the output (default 2) 19 | - Add `--output_file 'path/to/file'` to specify where the .json or .csv should be left 20 | 21 | 22 | #### Detailed API Usage 23 | Start by loading in a book 24 | ```python 25 | book = load_book('path/to/book.txt') 26 | ``` 27 | Split the book into individual sentences, sequences of `n` words, or sequences of `n` characters by respectively running 28 | ```python 29 | sequences = get_sentence_sequences(book) 30 | sequences = get_word_sequences(book, n=50) 31 | sequences = get_character_sequences(book, n=200) 32 | ``` 33 | Manually input a list of character names or automatically extract a list of 'plausible' character names by respectively using 34 | ```python 35 | characters = load_characters('path/to/character_list.csv') 36 | characters = extract_character_names(book) 37 | ``` 38 | Find instances of each character in each sequence with `find_connections()`, enumerate their cooccurences with `calculate_cooccurence()`, and transform that into a more easily interpretable format using `get_interaction_df()` 39 | ```python 40 | df = find_connections(sequences, characters) 41 | cooccurence = calculate_cooccurence(df) 42 | interaction_df = get_interaction_df(cooccurence, characters) 43 | ``` 44 | The resulting dataframe can be easily transform into a networkx graph using 45 | ```python 46 | nx.from_pandas_dataframe(interaction_df, 47 | source='source', 48 | target='target') 49 | ``` 50 | From there, all sorts of interesting analysis can be done. See the project's [associated jupyter notebooks](01%20-%20Intro%20to%20Bookworm.ipynb) and the [networkx documentation](https://networkx.github.io/documentation/stable/index.html) for more details. 51 | 52 | ### Slides 53 | I presented a bunch of this stuff at 54 | - :statue_of_liberty: [PyData NYC 17](data/other-files/Bookworm,%20PyData%20NYC%2017.pdf) 55 | - :beers: [Databeers London](data/other-files/Bookworm,%20Databeers%20London%202018.pdf) 56 | -------------------------------------------------------------------------------- /data/raw/characters_ij.csv: -------------------------------------------------------------------------------- 1 | Miles Penn 2 | Caryn Vaught,Caryn 3 | Sharyn Vaught,Sharyn 4 | Ann Kittenplan,Kittenplan 5 | Erica Siress 6 | Jennie Bash 7 | Amy WIngo 8 | Lori Clow 9 | Shoshana Abrams 10 | Carol Spodek 11 | Frances L. Unwin,Unwin 12 | Tina Echt,Echt 13 | Gretchen Holt 14 | Jolene Criess 15 | Felicity Zwieg,Zwieg 16 | Zoltan Csikzentmihalyi 17 | Bernard Makulic 18 | Stephan Wagenknecht 19 | Jeff Wax 20 | Chip Sweeny 21 | Todd "Postal Weight" Possalthwaite,Possalthwaite,Postal Weight 22 | Otis P. Lord,Lord 23 | Esteban Reyes 24 | Guglielmo Redondo 25 | Eliot Kornspan 26 | Cisne 27 | Jeffrey Joseph Penn 28 | Tim "Sleepy TP" Peterson,Peterson,Sleepy TP 29 | Kieran McKenna 30 | Brian van Vleck,van Vleck 31 | Lamont Chu 32 | Audern Tallat-Kelpsa 33 | Phillip Traub 34 | Josh Gopnik 35 | Virgilio 36 | Evan Ingersoll,Ingersoll 37 | Ortho "The Darkness" Stice,Stice,Ortho,The Darkness 38 | Kenn Blott 39 | Petropolis Khan,Petropolis 40 | Graham "Yard-Guard" Rader,Yard Guard 41 | Kent Blott 42 | Lyle 43 | Coach Kirk White 44 | Dean of Admissions 45 | Sirector of Composition 46 | Dean of Athletic Affairs 47 | Dean of Academic Affairs 48 | "U.S.S" Millicent Kent 49 | Idris "Id" Arslanian,Arslanian 50 | Peter Beak 51 | Carl "Mobes" Whale 52 | Trevor "Axhandle" Axford,Axford,Axhandle 53 | Diane Prins 54 | Bernadette Longley 55 | Kyle D Coyle 56 | Keith Freer,Freer,The Viking 57 | John Wayne 58 | James Struck,Struck 59 | Hugh Pemberton,Pemberton 60 | Tall Paul Shaw,TP Shaw,Shaw 61 | Jim Troeltsch,Troeltsch 62 | Ted Schacht,Schacht 63 | van Slack 64 | Stockhausen 65 | Gloeckner 66 | Bernard Wayne 67 | Noreen Lace-Forche 68 | Maureen Hooley 69 | Tom Veals 70 | Fully Functional Phil 71 | Johnny Gentle 72 | Mexican President 73 | Canadian President 74 | Rodney Tine,Rod the god,Rodney "The God" Tine 75 | Bridget C. Boone,Boone 76 | Hal 77 | Dymphna 78 | Mario 79 | Schtitt 80 | Poutrincourt 81 | Thode 82 | Ruth 83 | Rik Dunkel 84 | Nwangi 85 | Corbett Thorp 86 | Cantrell 87 | Donnie Scott 88 | Tex Watson 89 | Neil Hartigan 90 | deLint 91 | Miriam Pricket 92 | Flottman 93 | Fentress 94 | Lingley 95 | Pettijohn 96 | Chawaf 97 | Urquhart 98 | Disney R. Leith 99 | Melinda 100 | Vogelsong 101 | Rutherford Keck 102 | Crosby Baum 103 | Reeves Mainwaring 104 | Iaccarino 105 | Molly Cantrell Notkin,Notkin 106 | Barry Loach,Loach 107 | The Moms,Avril,Mondragon 108 | Pemulis 109 | Dick Willis 110 | Thomas M. Flatto 111 | Dick Desai 112 | Luria Perec,Luria P 113 | Fortier 114 | Broullime 115 | Balbalis 116 | Ossowircke 117 | Beausoleil 118 | Tassigny 119 | Desjardins 120 | Joubet 121 | Harv 122 | Kevin Bain 123 | Marlon Bain,Marlon 124 | Henri F. Hoyne,Henri 125 | Miriam Hoyne,Miriam 126 | Steeply,Hugh 127 | Mo Cheery 128 | Muminsky 129 | Orin 130 | Marathe,Remy 131 | Gertraud 132 | Nickerson 133 | Smothergill 134 | Flechette 135 | Brandeis 136 | Guillaume Duplessis,Guillaume,Duplessis 137 | Bertraund 138 | Lucien 139 | Kate Gompert,Gompert 140 | Erdedy 141 | Ruth van Cleve 142 | Burt F. Smith,Burt 143 | Poor Tony,Krause 144 | Emil Minty,Emil,yrstruly 145 | Susan T. Cheese 146 | Bridget Tenderhole 147 | Lolasister 148 | Equus Reese 149 | Stokeley "Dark Star" McNair,Stokeley,Dark Star,DarkStar,McNair 150 | Dr Wo 151 | Himself,Mad stork,Jim Icandenza,James Incandenza 152 | Ken Johnson 153 | Elizabeth Tavis 154 | Lateral,Alice Moore 155 | Charles Tavis,Tavis 156 | Barry Loach 157 | Therese 158 | Veach 159 | Slodoban 160 | Rusk 161 | Zegarelli 162 | Kenkle 163 | FDV,Harde,Fall Down Very 164 | Brandt 165 | Calvin Thrust 166 | Didi Neaves 167 | Roy Tony 168 | Clenette Henderson 169 | Dolores Epps 170 | Columbus Epps 171 | Doony,Glynn 172 | Wade McDade,McDade 173 | Alfonso Parias-Carbo,Parias-Carbo 174 | Tingley 175 | April Cortelyu 176 | David Krone 177 | Chandler Foss,Foss 178 | Morris Hanley 179 | Jennifer Belbin 180 | Selwyn 181 | Hester,Thrale 182 | Kubitz 183 | Nell Gunther 184 | Gavin Diehl,Gavin,Diehl 185 | Tiny Ewell,Ewell 186 | Montesian 187 | Annie Parrot 188 | Mildred Bonk Green 189 | Bruce Green 190 | Foltz 191 | Geoff,Geoffrey Day 192 | Tommy Doocey 193 | Yolanda 194 | Randy,Lenz 195 | Bobby C 196 | Purpleboy 197 | Kely Vinoy 198 | Pamela Hoffman-Jeep,Hoffman-Jeep 199 | Lobokulas 200 | Joelle,van Dyne,Lucille 201 | Lady Delphina 202 | attache,saudi 203 | wraith 204 | Pendleton 205 | Prissburger 206 | Cathy,Kathy 207 | Glenn,Glenn K 208 | Bud O 209 | Sven S 210 | Jack J 211 | Dicky N 212 | Tamara N 213 | Louise B 214 | John L 215 | Ferocious Francis,Francis 216 | Bob Death 217 | Whitey Sorkin,Sorkin 218 | Sixties Bob,Bob Monroe 219 | Eighties Bill 220 | Gwendine O'Shay 221 | Gately,Don 222 | Quo Vadis 223 | Eugene,Fackelmann 224 | Martinez 225 | Revere ADA 226 | Waite 227 | Sir Osis of Thuliver 228 | -------------------------------------------------------------------------------- /bookworm/analyse.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | import pandas as pd 3 | import numpy as np 4 | import networkx as nx 5 | from nltk.tokenize import word_tokenize 6 | from .build_network import * 7 | 8 | 9 | def character_density(book_path): 10 | ''' 11 | number of central characters divided by the total number of words in a novel 12 | 13 | Parameters 14 | ---------- 15 | book_path : string (required) 16 | path to txt file containing full text of book to be analysed 17 | 18 | Returns 19 | ------- 20 | density : float 21 | number of characters in book / number of words in book 22 | ''' 23 | book = load_book(book_path) 24 | book_length = len(word_tokenize(book)) 25 | book_graph = nx.from_pandas_dataframe(bookworm(book_path), 26 | source='source', 27 | target='target') 28 | n_characters = len(book_graph.nodes()) 29 | return n_characters / book_length 30 | 31 | 32 | def split_book(book, n_sections=10, cumulative=True): 33 | ''' 34 | Split a book into n equal parts, with optional cumulative aggregation 35 | 36 | Parameters 37 | ---------- 38 | book : string (required) 39 | the book to be split 40 | n_sections : (optional) 41 | the number of sections which we want to split our book into 42 | cumulative : bool (optional) 43 | If true, the returned sections will be cumulative, ie all 44 | will start at the book's beginning and end at evenly distributed 45 | points throughout the book 46 | 47 | Returns 48 | ------- 49 | split_book : list 50 | the given book split into the specified number of even (or, if 51 | cumulative is set to True, uneven) sections 52 | ''' 53 | book_sequences = get_sentence_sequences(book) 54 | split_book = np.array_split(np.array(book_sequences), n_sections) 55 | 56 | if cumulative is True: 57 | split_book = [np.concatenate(split_book[:pos + 1]) 58 | for pos, section in enumerate(split_book)] 59 | 60 | return split_book 61 | 62 | 63 | def chronological_network(book_path, n_sections=10, cumulative=True): 64 | ''' 65 | Split a book into n equal parts, with optional cumulative aggregation, and 66 | return a dictionary of assembled character graphs 67 | 68 | Parameters 69 | ---------- 70 | book_path : string (required) 71 | path to the .txt file containing the book to be split 72 | n_sections : (optional) 73 | the number of sections which we want to split our book into 74 | cumulative : bool (optional) 75 | If true, the returned sections will be cumulative, ie all will start at 76 | the book's beginning and end at evenly distributed points throughout 77 | the book 78 | 79 | Returns 80 | ------- 81 | graph_dict : dict 82 | a dictionary containing the graphs of each split book section 83 | keys = section index 84 | values = nx.Graph describing the character graph in the specified book 85 | section 86 | ''' 87 | book = load_book(book_path) 88 | sections = split_book(book, n_sections, cumulative) 89 | graph_dict = {} 90 | 91 | for i, section in enumerate(sections): 92 | characters = extract_character_names(' '.join(section)) 93 | df = find_connections(sequences=section, characters=characters) 94 | cooccurence = calculate_cooccurence(df) 95 | interaction_df = get_interaction_df(cooccurence, threshold=2) 96 | 97 | graph_dict[i] = nx.from_pandas_dataframe(interaction_df, 98 | source='source', 99 | target='target') 100 | return graph_dict 101 | 102 | 103 | def select_k(spectrum): 104 | ''' 105 | Returns k, where the top k eigenvalues of the graph's laplacian describe 90 106 | percent of the graph's complexiities. 107 | 108 | Parameters 109 | ---------- 110 | spectrum : type (required optional) 111 | the laplacian spectrum of the graph in question 112 | 113 | Returns 114 | ------- 115 | k : int 116 | denotes the top k eigenvalues of the graph's laplacian spectrum, 117 | explaining 90 percent of its complexity (or containing 90 percent of 118 | its energy) 119 | ''' 120 | if sum(spectrum) == 0: 121 | return len(spectrum) 122 | 123 | running_total = 0 124 | for i in range(len(spectrum)): 125 | running_total += spectrum[i] 126 | if (running_total / sum(spectrum)) >= 0.9: 127 | return i + 1 128 | 129 | return len(spectrum) 130 | 131 | 132 | def graph_similarity(graph_1, graph_2): 133 | ''' 134 | Computes the similarity of two graphs based on their laplacian spectra, 135 | returning a value between 0 and inf where a score closer to 0 is indicative 136 | of a more similar network 137 | 138 | Parameters 139 | ---------- 140 | graph_1 : networkx.Graph (required) 141 | graph_2 : networkx.Graph (required) 142 | 143 | Returns 144 | ------- 145 | similarity : float 146 | the similarity score of the two graphs where a value closer to 0 is 147 | indicative of a more similar pair of networks 148 | ''' 149 | laplacian_1 = nx.spectrum.laplacian_spectrum(graph_1) 150 | laplacian_2 = nx.spectrum.laplacian_spectrum(graph_2) 151 | 152 | k_1 = select_k(laplacian_1) 153 | k_2 = select_k(laplacian_2) 154 | k = min(k_1, k_2) 155 | 156 | return sum((laplacian_1[:k] - laplacian_2[:k])**2) 157 | 158 | 159 | def comparison_df(graph_dict): 160 | ''' 161 | takes an assortment of novels and computes their simlarity, based on their 162 | laplacian spectra 163 | 164 | Parameters 165 | ---------- 166 | graph_dict : dict (required) 167 | keys = book title 168 | values = character graph 169 | 170 | Returns 171 | ------- 172 | comparison : pandas.DataFrame 173 | columns = book titles 174 | indexes = book titles 175 | values = measure of the character graph similarity of books 176 | ''' 177 | books = list(graph_dict.keys()) 178 | comparison = {book_1: {book_2: graph_similarity(graph_dict[book_1], 179 | graph_dict[book_2]) 180 | for book_2 in books} for book_1 in books} 181 | 182 | return pd.DataFrame(comparison) 183 | -------------------------------------------------------------------------------- /bookworm/build_network.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import nltk 3 | import pandas as pd 4 | import numpy as np 5 | import spacy 6 | from nltk.tokenize import word_tokenize 7 | import string 8 | 9 | 10 | def load_book(book_path, lower=False): 11 | ''' 12 | Reads in a novel from a .txt file, and returns it in (optionally 13 | lowercased) string form 14 | 15 | Parameters 16 | ---------- 17 | book_path : string (required) 18 | path to txt file containing full text of book to be analysed 19 | lower : bool (optional) 20 | If True, the returned string will be lowercased; 21 | If False, the returned string will retain its original case formatting. 22 | 23 | Returns 24 | ------- 25 | book : string 26 | book in string form 27 | ''' 28 | with open(book_path) as f: 29 | book = f.read() 30 | if lower: 31 | book = book.lower() 32 | return book 33 | 34 | 35 | def load_characters(charaters_path): 36 | ''' 37 | Reads in a .csv file of character names 38 | 39 | Parameters 40 | ---------- 41 | charaters_path : string (required) 42 | path to csv file containing full list of characters to be examined. 43 | Each character should take up one line of the file. If the character is 44 | referred to by multiple names, nicknames or sub-names within their 45 | full name, these should be split by commas, eg: 46 | Harry, Potter 47 | Lord, Voldemort, You-Know-Who 48 | Giant Squid 49 | 50 | Returns 51 | ------- 52 | characters : list 53 | list of tuples naming characters in text 54 | ''' 55 | with open(charaters_path) as f: 56 | reader = csv.reader(f) 57 | characters = [tuple(name.lower()+' ' for name in row) for row in reader] 58 | return characters 59 | 60 | 61 | def remove_punctuation(input_string): 62 | ''' 63 | Removes all punctuation from an input string 64 | 65 | Parameters 66 | ---------- 67 | input_string : string (required) 68 | input string 69 | 70 | Returns 71 | ------- 72 | clean_string : string 73 | clean string 74 | ''' 75 | return input_string.translate(str.maketrans('', '', string.punctuation+'’')) 76 | 77 | 78 | def extract_character_names(book): 79 | ''' 80 | Automatically extracts lists of plausible character names from a book 81 | 82 | Parameters 83 | ---------- 84 | book : string (required) 85 | book in string form (with original upper/lowercasing intact) 86 | 87 | Returns 88 | ------- 89 | characters : list 90 | list of plasible character names 91 | ''' 92 | nlp = spacy.load('en') 93 | stopwords = nltk.corpus.stopwords.words('english') 94 | 95 | words = [remove_punctuation(w) for w in book.split()] 96 | unique_words = list(set(words)) 97 | 98 | characters = [word.text for word in nlp(' '.join(unique_words)) if word.pos_ == 'PROPN'] 99 | characters = [c for c in characters if len(c) > 2] 100 | characters = [c for c in characters if c.istitle()] 101 | characters = [c for c in characters if not (c[-1] == 's' and c[:-1] in characters)] 102 | characters = list(set([c.title() for c in [c.lower() for c in characters]]) - set(stopwords)) 103 | 104 | return [tuple([c + ' ']) for c in set(characters)] 105 | 106 | 107 | def get_sentence_sequences(book): 108 | ''' 109 | Splits a book into its constituent sentences 110 | 111 | Parameters 112 | ---------- 113 | book : string (required) 114 | book in string form 115 | 116 | Returns 117 | ------- 118 | sentences : list 119 | list of strings, where each string is a sentence in the novel as 120 | interpreted by NLTK's tokenize() function. 121 | ''' 122 | detector = nltk.data.load('tokenizers/punkt/english.pickle') 123 | sentences = detector.tokenize(book) 124 | return sentences 125 | 126 | 127 | def get_word_sequences(book, n=50): 128 | ''' 129 | Takes a book and splits it into its constituent words, returning a list of 130 | substrings which comprise the book, whose lengths are determined by a set 131 | number of words (default = 50). 132 | 133 | Parameters 134 | ---------- 135 | book : string (required) 136 | book in string form 137 | n : int (optional) 138 | number of words to be contained in each returned sequence (default = 50) 139 | 140 | Returns 141 | ------- 142 | sequences : list 143 | list of strings, where each string is a list of n words as interpreted 144 | by NLTK's word_tokenize() function. 145 | ''' 146 | book_words = word_tokenize(book) 147 | return [' '.join(book_words[i: i+n]) for i in range(0, len(book_words), n)] 148 | 149 | 150 | def get_character_sequences(book, n=200): 151 | ''' 152 | Takes a book and splits it into a list of substrings of length n 153 | (default = 200). 154 | 155 | Parameters 156 | ---------- 157 | book : string (required) 158 | book in string form 159 | n : int (optional) 160 | number of characters to be contained in each returned sequence 161 | (default = 200) 162 | 163 | Returns 164 | ------- 165 | sequences : list 166 | list of strings comprising the book, where each string is of length n. 167 | ''' 168 | return [''.join(book[i: i+n]) for i in range(0, len(book), n)] 169 | 170 | 171 | def find_connections(sequences, characters): 172 | ''' 173 | Takes a novel and its character list and counts instances of each character 174 | in each sequence. 175 | 176 | Parameters 177 | ---------- 178 | sequences : list (required) 179 | list of substrings representing the novel to be analysed 180 | characters : list (required) 181 | list of charater names (as tuples) 182 | 183 | Returns 184 | ------- 185 | df : pandas.DataFrame 186 | columns = character names 187 | indexes = sequences 188 | values = counts of instances of character name in sequence 189 | ''' 190 | if any(len(names) > 1 for names in characters): 191 | df = pd.DataFrame({str(character): 192 | {sequence: sum([sequence.count(name) for name in character]) 193 | for sequence in sequences} 194 | for character in characters}) 195 | else: 196 | characters = [c[0] for c in characters] 197 | df = pd.DataFrame([[sequence.count(character) 198 | for character in characters] 199 | for sequence in sequences], 200 | index=sequences, 201 | columns=characters) 202 | return df 203 | 204 | def calculate_cooccurence(df): 205 | ''' 206 | Uses the dot product to calculate the number of times two characters appear 207 | in the same sequences. This is the core of the bookworm graph. 208 | 209 | Parameters 210 | ---------- 211 | df : pandas.DataFrame (required) 212 | columns = character names 213 | indexes = sequences 214 | values = counts of instances of character name in sequence 215 | 216 | Returns 217 | ------- 218 | cooccurence : pandas.DataFrame 219 | columns = character names 220 | indexes = character names 221 | values = counts of character name cooccurences in all sequences 222 | ''' 223 | characters = df.columns.values 224 | cooccurence = df.values.T.dot(df.values) 225 | np.fill_diagonal(cooccurence, 0) 226 | cooccurence = pd.DataFrame(cooccurence, columns=characters, index=characters) 227 | return cooccurence 228 | 229 | 230 | def get_interaction_df(cooccurence, threshold=0): 231 | ''' 232 | Produces an dataframe of interactions between characters using the 233 | cooccurence matrix of those characters. The return format is directly 234 | analysable by networkx in the construction of a graph of characters. 235 | 236 | Parameters 237 | ---------- 238 | cooccurence : pandas.DataFrame (required) 239 | columns = character names 240 | indexes = character names 241 | values = counts of character name cooccurences in all sequences 242 | threshold : int (optional) 243 | The minimum character interaction strength needed to be included in the 244 | returned interaction_df 245 | 246 | Returns 247 | ------- 248 | interaction_df : pandas.DataFrame 249 | DataFrame enumerating the strength of interactions between charcters. 250 | source = character one 251 | target = character two 252 | value = strength of interaction between character one and character two 253 | ''' 254 | rows, columns = np.where(np.triu(cooccurence.values, 1) > threshold) 255 | 256 | return pd.DataFrame(np.column_stack([cooccurence.index[rows], 257 | cooccurence.columns[columns], 258 | cooccurence.values[rows, columns]]), 259 | columns=['source', 'target', 'value']) 260 | 261 | 262 | def bookworm(book_path, charaters_path=None, threshold=2): 263 | ''' 264 | Wraps the full bookworm analysis from the raw .txt file's path, to 265 | production of the complete interaction dataframe. The returned dataframe is 266 | directly analysable by networkx using: 267 | 268 | nx.from_pandas_dataframe(interaction_df, 269 | source='source', 270 | target='target') 271 | 272 | Parameters 273 | ---------- 274 | book_path : string (required) 275 | path to txt file containing full text of book to be analysed 276 | charaters_path : string (optional) 277 | path to csv file containing full list of characters to be examined 278 | 279 | Returns 280 | ------- 281 | interaction_df : pandas.DataFrame 282 | DataFrame enumerating the strength of interactions between charcters. 283 | source = character one 284 | target = character two 285 | value = strength of interaction between character one and character two 286 | ''' 287 | book = load_book(book_path) 288 | sequences = get_sentence_sequences(book) 289 | 290 | if charaters_path is None: 291 | characters = extract_character_names(book) 292 | else: 293 | characters = load_characters(charaters_path) 294 | 295 | df = find_connections(sequences, characters) 296 | cooccurence = calculate_cooccurence(df) 297 | return get_interaction_df(cooccurence, threshold) 298 | -------------------------------------------------------------------------------- /01 - Intro to Bookworm.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Intro to Bookworm\n", 8 | "## Motivation\n", 9 | "Infinite Jest is a very long and complicated novel. There are a lot of brilliant resources connected to the book, which aim to help the reader stay afloat amongst the chaos of David Foster Wallace's obscure language, interwoven timelines and narratives, and the sprawling networks of characters. The [Infinite Jest Wiki](http://infinitejest.wallacewiki.com/david-foster-wallace/index.php?title=Infinite_Jest_Page_by_Page), for example, is insanely well documented and I'd recommend it to anyone reading the book. \n", 10 | "One of the most interesting resources I found while reading was Sam Potts' [Infinite Jest Diagram](http://www.sampottsinc.com/ij/). \n", 11 | "\n", 12 | "![alt text](https://a.fastcompany.net/upload/IJ_Diagram-Huge-A.jpg \"IJmap\")\n", 13 | "\n", 14 | "I went back to the image once or twice while I was reading IJ to work out who a character was and how they were connected to the scene. It's a fun resource to have access to while reading something so deliberately scattered. \n", 15 | "However, Infinite Jest isn't the only \"big\" book out there, and as far as I know the network above was drawn up entirely by hand. I thought it would be nice to have something like this for anything I was reading. It might also function as an interesting learning resource - either for kids at a young, early-reader stage with simple books and small character networks, or for people learning about network analysis who have never bothered reading [Les Miserables](https://bl.ocks.org/mbostock/4062045) (again, as far as I know all of the standard example graph datasets like Les Mis and The Karate Kid were put together entirely by hand). \n", 16 | "I thought that with a bit of thought and testing, this process was probably automatable, and it is. I can now feed bookworm any novel and have it churn out a pretty network like the one above in seconds, without any prior knowledge of the story or its characters. By virtue of the way character connections are measured, it can also tell you the relative strength of all links between characters.\n", 17 | "\n", 18 | "## Getting Started\n", 19 | "Before we start, let's import all of the code in the [bookworm module](bookworm/). I'll explain what each function does as we move through the notebook - we'll be covering most of [build_network.py](bookworm/build_network.py) here." 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 1, 25 | "metadata": { 26 | "collapsed": true 27 | }, 28 | "outputs": [], 29 | "source": [ 30 | "from bookworm import *" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "The fisrt thing we'll do is load in a book and a list of its characters. These operations are both pretty simple. The book is loaded in as one long string from a `.txt` file. Character lists are stored in a `.csv`, with all potential names for a character stored on each row. They're loaded in as tuples of names in a list of characters. " 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": 2, 43 | "metadata": { 44 | "collapsed": true 45 | }, 46 | "outputs": [], 47 | "source": [ 48 | "book = load_book('data/raw/ij.txt', lower=True)\n", 49 | "characters = load_characters('data/raw/characters_ij.csv')" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "Then we split the book down into sections. Bookworm works by looking for _coocurrence_ of characters in these sections of the text as a proxy for their connectedness. It's a very simple trick which works stupidly well. \n", 57 | "There are a few ways we can break down the book into sections:\n", 58 | "- `get_sentence_sequences()` uses [NLTK](http://www.nltk.org/)'s standard `.tokenize()` function to split the book into sentences. \n", 59 | "- `get_word_sequences()` uses [NLTK](http://www.nltk.org/)'s `word_tokenize()` to split the book into words, of which it will then select ordered lists of length `n` (default 40). \n", 60 | "- `get_character_sequences()` uses python builtins to split it into substrings of length `n` (default 200). \n", 61 | "\n", 62 | "Fundamentally, they all return a list of strings which each cover a very small section of the novel. For simplicity's sake we're going to use the sentence-wise splitter." 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 3, 68 | "metadata": { 69 | "collapsed": true 70 | }, 71 | "outputs": [], 72 | "source": [ 73 | "sequences = get_sentence_sequences(book)" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "Now comes the interesting bit. We've assembled our cast, and moved the text that they inhabit into a nice, machine-interpretable format. \n", 81 | "What we want to generate now is the blank table below which describes the presence of a character in a sentence. At this point, Bookworm hasn't really 'read' any of the text so all of the interactions between characters and sentences (where each cell in the table represents an interaction) are set to 0:\n", 82 | "\n", 83 | "| | character 1 | character 2 | character 3 |\n", 84 | "|------------|-------------|-------------|-------------|\n", 85 | "| sentence 1 | 0 | 0 | 0 |\n", 86 | "| sentence 2 | 0 | 0 | 0 |\n", 87 | "| sentence 3 | 0 | 0 | 0 |\n", 88 | "| sentence 4 | 0 | 0 | 0 |\n", 89 | "\n", 90 | "The first bit of the `find_connections()` sets up the blank table above. " 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": 4, 96 | "metadata": { 97 | "collapsed": true 98 | }, 99 | "outputs": [], 100 | "source": [ 101 | "df = find_connections(sequences, characters)" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "Next, it iterates through the list of sentences it has been fed, checking for an instance of each character. If it finds a character in the sentence, it marks their presence with a 1. \n", 109 | "So if **character 1** appears with **character 2** in sentence 1, and with **character 3** in sentence 2, we would see the following, with the rest of the cells remaining blank:\n", 110 | "\n", 111 | "| | character 1 | character 2 | character 3 |\n", 112 | "|------------|-------------|-------------|-------------|\n", 113 | "| sentence 1 | 1 | 1 | 0 |\n", 114 | "| sentence 2 | 1 | 0 | 1 |\n", 115 | "| sentence 3 | 0 | 0 | 0 |\n", 116 | "| sentence 4 | 0 | 0 | 0 |\n", 117 | "\n", 118 | "In the next stage, we enumerate characters coocurence with one another. We can compute this very quickly by taking the dot product of the table with its transpose." 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 5, 124 | "metadata": { 125 | "collapsed": true 126 | }, 127 | "outputs": [], 128 | "source": [ 129 | "cooccurence = calculate_cooccurence(df)" 130 | ] 131 | }, 132 | { 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "`calculate_cooccurence()` does this computation and then wipes out any interaction of a character with themselves. For the table above, this would give us:\n", 137 | "\n", 138 | "| | character 1 | character 2 | character 3 |\n", 139 | "|-------------|-------------|-------------|-------------|\n", 140 | "| character 1 | 0 | 1 | 1 |\n", 141 | "| character 2 | 1 | 0 | 0 |\n", 142 | "| character 3 | 1 | 0 | 0 |\n", 143 | "\n", 144 | "showing that **character 1** has interacted with **character 2** and **character 3**, but **character 2** and **character 3** haven't interacted. Note the symmetry across the diagonal...\n", 145 | "\n", 146 | "The cooccurence matrix we're referring to here is also known as an _adjacency matrix_ - I might use the terms interchangably from here on. \n", 147 | "\n", 148 | "The example table above is miniscule in comparison to the dozens of characters who might turn up in a reasonably sized novel, and the hundreds or thousands of opportunities they have to interact with one another. The coocurence matrix in reality is likely to contain much larger numbers between characters who regularly appear in the same sentences. Unless we're working with a _really_ tiny, incestuous network, this coocurence matrix is also probably going to be pretty sparse. For that reason it'll often make sense to store it as a sparse matrix:" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": 6, 154 | "metadata": {}, 155 | "outputs": [], 156 | "source": [ 157 | "cooccurence = cooccurence.to_sparse()" 158 | ] 159 | }, 160 | { 161 | "cell_type": "markdown", 162 | "metadata": {}, 163 | "source": [ 164 | "That's the essence of what bookworm does, and everything from here onwards is just play. It really is that simple. Once we have an adjacency matrix of our characters, all of the graph theory falls into place.\n", 165 | "\n", 166 | "So, now we can show off a few some results! Despite describing a set of tiny matrices above, we've really been computing all of Infinite Jest's massiveness while working through the notebook.\n", 167 | "\n", 168 | "We can print the strongest relationships for a chosen character using the function below:" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": 7, 174 | "metadata": { 175 | "collapsed": true, 176 | "scrolled": true 177 | }, 178 | "outputs": [], 179 | "source": [ 180 | "def print_five_closest(character):\n", 181 | " print('-'*len(str(character))\n", 182 | " + '\\n' + str(character) + '\\n'\n", 183 | " + '-'*len(str(character)))\n", 184 | " \n", 185 | " top_five = (cooccurence[str(character)]\n", 186 | " .sort_values(ascending=False)\n", 187 | " .index.values\n", 188 | " [:5])\n", 189 | " \n", 190 | " for name in top_five:\n", 191 | " print(name)" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "Applying this to 5 characters at random:" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": 8, 204 | "metadata": {}, 205 | "outputs": [ 206 | { 207 | "name": "stdout", 208 | "output_type": "stream", 209 | "text": [ 210 | "------------\n", 211 | "('joubet ',)\n", 212 | "------------\n", 213 | "('marathe ', 'remy ')\n", 214 | "('desjardins ',)\n", 215 | "('zoltan csikzentmihalyi ',)\n", 216 | "('fdv ', 'harde ', 'fall down very ')\n", 217 | "('gavin diehl ', 'gavin ', 'diehl ')\n", 218 | "\n", 219 | "----------------------------------------------------\n", 220 | "('guillaume duplessis ', 'guillaume ', 'duplessis ')\n", 221 | "----------------------------------------------------\n", 222 | "('marathe ', 'remy ')\n", 223 | "('steeply ', 'hugh ')\n", 224 | "('fortier ',)\n", 225 | "('luria perec ', 'luria p ')\n", 226 | "('zoltan csikzentmihalyi ',)\n", 227 | "\n", 228 | "-------------------------------------\n", 229 | "('the moms ', 'avril ', 'mondragon ')\n", 230 | "-------------------------------------\n", 231 | "('hal ',)\n", 232 | "('orin ',)\n", 233 | "('mario ',)\n", 234 | "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')\n", 235 | "('joelle ', 'van dyne ', 'lucille ')\n", 236 | "\n", 237 | "-------------\n", 238 | "('dymphna ',)\n", 239 | "-------------\n", 240 | "('petropolis khan ', 'petropolis ')\n", 241 | "('zoltan csikzentmihalyi ',)\n", 242 | "('evan ingersoll ', 'ingersoll ')\n", 243 | "('gately ', 'don ')\n", 244 | "('fully functional phil ',)\n", 245 | "\n", 246 | "------------------------\n", 247 | "('dean of admissions ',)\n", 248 | "------------------------\n", 249 | "('zoltan csikzentmihalyi ',)\n", 250 | "('dolores epps ',)\n", 251 | "('gavin diehl ', 'gavin ', 'diehl ')\n", 252 | "('gately ', 'don ')\n", 253 | "('fully functional phil ',)\n", 254 | "\n" 255 | ] 256 | } 257 | ], 258 | "source": [ 259 | "from random import randint\n", 260 | "\n", 261 | "for i in range(5):\n", 262 | " print_five_closest(characters[randint(0, len(characters))])\n", 263 | " print()" 264 | ] 265 | }, 266 | { 267 | "cell_type": "markdown", 268 | "metadata": {}, 269 | "source": [ 270 | "Those all seem to make sense... Lets try with a few characters who we know about in more detail" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": 9, 276 | "metadata": {}, 277 | "outputs": [ 278 | { 279 | "name": "stdout", 280 | "output_type": "stream", 281 | "text": [ 282 | "-------------------------------------\n", 283 | "('the moms ', 'avril ', 'mondragon ')\n", 284 | "-------------------------------------\n", 285 | "('hal ',)\n", 286 | "('orin ',)\n", 287 | "('mario ',)\n", 288 | "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')\n", 289 | "('joelle ', 'van dyne ', 'lucille ')\n" 290 | ] 291 | } 292 | ], 293 | "source": [ 294 | "print_five_closest(('the moms ', 'avril ', 'mondragon '))" 295 | ] 296 | }, 297 | { 298 | "cell_type": "code", 299 | "execution_count": 10, 300 | "metadata": {}, 301 | "outputs": [ 302 | { 303 | "name": "stdout", 304 | "output_type": "stream", 305 | "text": [ 306 | "------------------------------------\n", 307 | "('joelle ', 'van dyne ', 'lucille ')\n", 308 | "------------------------------------\n", 309 | "('orin ',)\n", 310 | "('gately ', 'don ')\n", 311 | "('the moms ', 'avril ', 'mondragon ')\n", 312 | "('erdedy ',)\n", 313 | "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')\n" 314 | ] 315 | } 316 | ], 317 | "source": [ 318 | "print_five_closest(('joelle ', 'van dyne ', 'lucille '))" 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "execution_count": 11, 324 | "metadata": {}, 325 | "outputs": [ 326 | { 327 | "name": "stdout", 328 | "output_type": "stream", 329 | "text": [ 330 | "-------------\n", 331 | "('pemulis ',)\n", 332 | "-------------\n", 333 | "('hal ',)\n", 334 | "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')\n", 335 | "('jim troeltsch ', 'troeltsch ')\n", 336 | "('james struck ', 'struck ')\n", 337 | "('keith freer ', 'freer ', 'the viking ')\n" 338 | ] 339 | } 340 | ], 341 | "source": [ 342 | "print_five_closest(('pemulis ',))" 343 | ] 344 | }, 345 | { 346 | "cell_type": "code", 347 | "execution_count": 12, 348 | "metadata": {}, 349 | "outputs": [ 350 | { 351 | "name": "stdout", 352 | "output_type": "stream", 353 | "text": [ 354 | "-----------------\n", 355 | "('bruce green ',)\n", 356 | "-----------------\n", 357 | "('randy ', 'lenz ')\n", 358 | "('gately ', 'don ')\n", 359 | "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')\n", 360 | "('kate gompert ', 'gompert ')\n", 361 | "('tommy doocey ',)\n" 362 | ] 363 | } 364 | ], 365 | "source": [ 366 | "print_five_closest(('bruce green ',))" 367 | ] 368 | }, 369 | { 370 | "cell_type": "markdown", 371 | "metadata": {}, 372 | "source": [ 373 | "Yep... Compare the results we've generated to the ones in the diagram at the top of the notebook.\n", 374 | "\n", 375 | "# Same code, different book\n", 376 | "Lets run the whole thing for an entirely different book and see whether we get similarly positive results. This time, Harry Potter and The Philosopher's Stone - chosen because you're more likely to have some contextual knowledge of who's who and what's what in that book." 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": 13, 382 | "metadata": {}, 383 | "outputs": [], 384 | "source": [ 385 | "book = load_book('data/raw/hp_philosophers_stone.txt', lower=True)\n", 386 | "characters = load_characters('data/raw/characters_hp.csv')\n", 387 | "sequences = get_sentence_sequences(book)\n", 388 | "\n", 389 | "df = find_connections(sequences, characters)\n", 390 | "cooccurence = calculate_cooccurence(df).to_sparse()" 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": 14, 396 | "metadata": {}, 397 | "outputs": [ 398 | { 399 | "data": { 400 | "text/plain": [ 401 | "[('vernon ', ' dursley '),\n", 402 | " ('petunia ', ' dursley '),\n", 403 | " ('dudley ', ' duddy '),\n", 404 | " ('lily ',),\n", 405 | " ('james ',)]" 406 | ] 407 | }, 408 | "execution_count": 14, 409 | "metadata": {}, 410 | "output_type": "execute_result" 411 | } 412 | ], 413 | "source": [ 414 | "characters[:5]" 415 | ] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "execution_count": 15, 420 | "metadata": {}, 421 | "outputs": [ 422 | { 423 | "name": "stdout", 424 | "output_type": "stream", 425 | "text": [ 426 | "----------------------\n", 427 | "('harry ', ' potter ')\n", 428 | "----------------------\n", 429 | "('ron ', ' weasley ')\n", 430 | "('hermione ', ' granger ')\n", 431 | "('hagrid ', ' rubeus ')\n", 432 | "('snape ', ' severus ')\n", 433 | "('dudley ', ' duddy ')\n" 434 | ] 435 | } 436 | ], 437 | "source": [ 438 | "print_five_closest(('harry ', ' potter '))" 439 | ] 440 | }, 441 | { 442 | "cell_type": "code", 443 | "execution_count": 16, 444 | "metadata": {}, 445 | "outputs": [ 446 | { 447 | "name": "stdout", 448 | "output_type": "stream", 449 | "text": [ 450 | "------------------------------------------\n", 451 | "('voldemort ', ' lord ', ' you-know-who ')\n", 452 | "------------------------------------------\n", 453 | "('harry ', ' potter ')\n", 454 | "('snape ', ' severus ')\n", 455 | "('quirrell ',)\n", 456 | "('dumbledore ', ' albus ')\n", 457 | "('ron ', ' weasley ')\n" 458 | ] 459 | } 460 | ], 461 | "source": [ 462 | "print_five_closest(('voldemort ', ' lord ', ' you-know-who '))" 463 | ] 464 | }, 465 | { 466 | "cell_type": "code", 467 | "execution_count": 17, 468 | "metadata": {}, 469 | "outputs": [ 470 | { 471 | "name": "stdout", 472 | "output_type": "stream", 473 | "text": [ 474 | "------------\n", 475 | "('crabbe ',)\n", 476 | "------------\n", 477 | "('goyle ',)\n", 478 | "('draco ', ' malfoy ')\n", 479 | "('harry ', ' potter ')\n", 480 | "('neville ', ' longbottom ')\n", 481 | "('george ',)\n" 482 | ] 483 | } 484 | ], 485 | "source": [ 486 | "print_five_closest(('crabbe ',))" 487 | ] 488 | }, 489 | { 490 | "cell_type": "code", 491 | "execution_count": 18, 492 | "metadata": {}, 493 | "outputs": [ 494 | { 495 | "name": "stdout", 496 | "output_type": "stream", 497 | "text": [ 498 | "----------\n", 499 | "('fred ',)\n", 500 | "----------\n", 501 | "('george ',)\n", 502 | "('ron ', ' weasley ')\n", 503 | "('harry ', ' potter ')\n", 504 | "('adrian pucey ',)\n", 505 | "('katie bell ',)\n" 506 | ] 507 | } 508 | ], 509 | "source": [ 510 | "print_five_closest(('fred ',))" 511 | ] 512 | }, 513 | { 514 | "cell_type": "markdown", 515 | "metadata": {}, 516 | "source": [ 517 | "Hopefully that's enough proof that bookworm does its job well. \n", 518 | "In the next notebook we'll examine how we can automatically extract character names from novels in order to automate the entirity of the bookworm process.\n", 519 | "\n", 520 | "[Home](https://github.com/harrisonpim/bookworm) | [02 - Character Building >](02%20-%20Character%20Building.ipynb)" 521 | ] 522 | }, 523 | { 524 | "cell_type": "code", 525 | "execution_count": null, 526 | "metadata": { 527 | "collapsed": true 528 | }, 529 | "outputs": [], 530 | "source": [] 531 | } 532 | ], 533 | "metadata": { 534 | "kernelspec": { 535 | "display_name": "Python [conda root]", 536 | "language": "python", 537 | "name": "conda-root-py" 538 | }, 539 | "language_info": { 540 | "codemirror_mode": { 541 | "name": "ipython", 542 | "version": 3 543 | }, 544 | "file_extension": ".py", 545 | "mimetype": "text/x-python", 546 | "name": "python", 547 | "nbconvert_exporter": "python", 548 | "pygments_lexer": "ipython3", 549 | "version": "3.5.3" 550 | } 551 | }, 552 | "nbformat": 4, 553 | "nbformat_minor": 2 554 | } 555 | -------------------------------------------------------------------------------- /bookworm/d3/bookworm.json: -------------------------------------------------------------------------------- 1 | {"links": [{"target": "('Kingdom ',)", "source": "('North ',)", "value": 3}, {"target": "('Amon ',)", "source": "('North ',)", "value": 2}, {"target": "('Road ',)", "source": "('North ',)", "value": 3}, {"target": "('Brandywine ',)", "source": "('Downs ',)", "value": 2}, {"target": "('Forest ',)", "source": "('Downs ',)", "value": 2}, {"target": "('South ',)", "source": "('Gondor ',)", "value": 2}, {"target": "('Emyn ',)", "source": "('Gondor ',)", "value": 2}, {"target": "('Glorfindel ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Gildor ',)", "source": "('Frodo ',)", "value": 4}, {"target": "('Legolas ',)", "source": "('Frodo ',)", "value": 3}, {"target": "('Merry ',)", "source": "('Frodo ',)", "value": 7}, {"target": "('Gandalf ',)", "source": "('Frodo ',)", "value": 13}, {"target": "('Moria ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Shire ',)", "source": "('Frodo ',)", "value": 4}, {"target": "('Pippin ',)", "source": "('Frodo ',)", "value": 11}, {"target": "('Gluin ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('River ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Baggins ',)", "source": "('Frodo ',)", "value": 7}, {"target": "('Elrond ',)", "source": "('Frodo ',)", "value": 3}, {"target": "('Sancho ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Company ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Brandywine ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Elvish ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Aragorn ',)", "source": "('Frodo ',)", "value": 8}, {"target": "('Bilbo ',)", "source": "('Frodo ',)", "value": 22}, {"target": "('Boromir ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Hill ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Drogo ',)", "source": "('Frodo ',)", "value": 2}, {"target": "('Sarn ',)", "source": "('Gebir ',)", "value": 3}, {"target": "('Company ',)", "source": "('Haldir ',)", "value": 2}, {"target": "('Merry ',)", "source": "('Bolger ',)", "value": 2}, {"target": "('Pippin ',)", "source": "('Bolger ',)", "value": 2}, {"target": "('Fatty ',)", "source": "('Bolger ',)", "value": 6}, {"target": "('Folco ',)", "source": "('Bolger ',)", "value": 2}, {"target": "('Fredegar ',)", "source": "('Bolger ',)", "value": 2}, {"target": "('River ',)", "source": "('Silverlode ',)", "value": 2}, {"target": "('Anduin ',)", "source": "('Silverlode ',)", "value": 2}, {"target": "('North ',)", "source": "('Kingdom ',)", "value": 3}, {"target": "('Frodo ',)", "source": "('Glorfindel ',)", "value": 2}, {"target": "('Hall ',)", "source": "('Master ',)", "value": 2}, {"target": "('Brandybuck ',)", "source": "('Master ',)", "value": 3}, {"target": "('Cerin ',)", "source": "('Amroth ',)", "value": 2}, {"target": "('South ',)", "source": "('Amroth ',)", "value": 2}, {"target": "('Nimrodel ',)", "source": "('Amroth ',)", "value": 2}, {"target": "('Bill ',)", "source": "('Poor ',)", "value": 2}, {"target": "('White ',)", "source": "('Delving ',)", "value": 2}, {"target": "('Michel ',)", "source": "('Delving ',)", "value": 5}, {"target": "('Frodo ',)", "source": "('Gildor ',)", "value": 4}, {"target": "('Pony ',)", "source": "('Prancing ',)", "value": 2}, {"target": "('Butterbur ',)", "source": "('Barliman ',)", "value": 2}, {"target": "('Elendil ',)", "source": "('Sword ',)", "value": 2}, {"target": "('North ',)", "source": "('Amon ',)", "value": 2}, {"target": "('Amroth ',)", "source": "('Cerin ',)", "value": 2}, {"target": "('Road ',)", "source": "('Loudwater ',)", "value": 2}, {"target": "('Ford ',)", "source": "('Loudwater ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Legolas ',)", "value": 3}, {"target": "('Merry ',)", "source": "('Legolas ',)", "value": 2}, {"target": "('Pippin ',)", "source": "('Legolas ',)", "value": 3}, {"target": "('Gluin ',)", "source": "('Legolas ',)", "value": 2}, {"target": "('Gimli ',)", "source": "('Legolas ',)", "value": 2}, {"target": "('Company ',)", "source": "('Legolas ',)", "value": 3}, {"target": "('Aragorn ',)", "source": "('Legolas ',)", "value": 4}, {"target": "('Smjagol ',)", "source": "('Deal ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Merry ',)", "value": 7}, {"target": "('Bolger ',)", "source": "('Merry ',)", "value": 2}, {"target": "('Legolas ',)", "source": "('Merry ',)", "value": 2}, {"target": "('Pippin ',)", "source": "('Merry ',)", "value": 21}, {"target": "('Fatty ',)", "source": "('Merry ',)", "value": 2}, {"target": "('Folco ',)", "source": "('Merry ',)", "value": 2}, {"target": "('Fredegar ',)", "source": "('Merry ',)", "value": 3}, {"target": "('Aragorn ',)", "source": "('Merry ',)", "value": 2}, {"target": "('Brandybuck ',)", "source": "('Merry ',)", "value": 3}, {"target": "('North ',)", "source": "('Road ',)", "value": 3}, {"target": "('Loudwater ',)", "source": "('Road ',)", "value": 2}, {"target": "('Captain ',)", "source": "('Road ',)", "value": 2}, {"target": "('Hoarwell ',)", "source": "('Road ',)", "value": 2}, {"target": "('Bridge ',)", "source": "('Road ',)", "value": 3}, {"target": "('River ',)", "source": "('Road ',)", "value": 2}, {"target": "('Bree ',)", "source": "('Road ',)", "value": 3}, {"target": "('Ford ',)", "source": "('Road ',)", "value": 4}, {"target": "('Hobbiton ',)", "source": "('Bywater ',)", "value": 2}, {"target": "('Dragon ',)", "source": "('Green ',)", "value": 2}, {"target": "('River ',)", "source": "('Lothlurien ',)", "value": 2}, {"target": "('Lady ',)", "source": "('Galadriel ',)", "value": 8}, {"target": "('Celeborn ',)", "source": "('Galadriel ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Gandalf ',)", "value": 13}, {"target": "('Shire ',)", "source": "('Gandalf ',)", "value": 3}, {"target": "('Gimli ',)", "source": "('Gandalf ',)", "value": 3}, {"target": "('Company ',)", "source": "('Gandalf ',)", "value": 2}, {"target": "('Thorin ',)", "source": "('Gandalf ',)", "value": 2}, {"target": "('Grey ',)", "source": "('Gandalf ',)", "value": 5}, {"target": "('Aragorn ',)", "source": "('Gandalf ',)", "value": 5}, {"target": "('Bilbo ',)", "source": "('Gandalf ',)", "value": 4}, {"target": "('Boromir ',)", "source": "('Gandalf ',)", "value": 2}, {"target": "('Tell ',)", "source": "('Gandalf ',)", "value": 2}, {"target": "('Master ',)", "source": "('Hall ',)", "value": 2}, {"target": "('Brandy ',)", "source": "('Hall ',)", "value": 4}, {"target": "('Road ',)", "source": "('Captain ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Moria ',)", "value": 2}, {"target": "('Elvish ',)", "source": "('Moria ',)", "value": 2}, {"target": "('River ',)", "source": "('Wilderland ',)", "value": 2}, {"target": "('Dbin ',)", "source": "('King ',)", "value": 2}, {"target": "('Elvish ',)", "source": "('Moon ',)", "value": 2}, {"target": "('Barliman ',)", "source": "('Butterbur ',)", "value": 2}, {"target": "('Maggot ',)", "source": "('Farmer ',)", "value": 2}, {"target": "('Dark ',)", "source": "('Mordor ',)", "value": 2}, {"target": "('Sauron ',)", "source": "('Mordor ',)", "value": 2}, {"target": "('Land ',)", "source": "('Mordor ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Shire ',)", "value": 4}, {"target": "('Gandalf ',)", "source": "('Shire ',)", "value": 3}, {"target": "('Baggins ',)", "source": "('Shire ',)", "value": 3}, {"target": "('Bree ',)", "source": "('Shire ',)", "value": 2}, {"target": "('West ',)", "source": "('Shire ',)", "value": 2}, {"target": "('Brandywine ',)", "source": "('Shire ',)", "value": 2}, {"target": "('Bilbo ',)", "source": "('Shire ',)", "value": 2}, {"target": "('Dark ',)", "source": "('Lord ',)", "value": 11}, {"target": "('Lady ',)", "source": "('Lord ',)", "value": 8}, {"target": "('Celeborn ',)", "source": "('Lord ',)", "value": 2}, {"target": "('Galadhrim ',)", "source": "('Lord ',)", "value": 3}, {"target": "('River ',)", "source": "('Minas ',)", "value": 2}, {"target": "('Tirith ',)", "source": "('Minas ',)", "value": 14}, {"target": "('Entwash ',)", "source": "('Minas ',)", "value": 2}, {"target": "('Ithil ',)", "source": "('Minas ',)", "value": 2}, {"target": "('Company ',)", "source": "('Minas ',)", "value": 2}, {"target": "('Aragorn ',)", "source": "('Minas ',)", "value": 2}, {"target": "('Tower ',)", "source": "('Minas ',)", "value": 2}, {"target": "('Isildur ',)", "source": "('Minas ',)", "value": 2}, {"target": "('Boromir ',)", "source": "('Minas ',)", "value": 2}, {"target": "('Road ',)", "source": "('Hoarwell ',)", "value": 2}, {"target": "('Bright ',)", "source": "('Bombadil ',)", "value": 2}, {"target": "('Mordor ',)", "source": "('Dark ',)", "value": 2}, {"target": "('Lord ',)", "source": "('Dark ',)", "value": 11}, {"target": "('Tower ',)", "source": "('Dark ',)", "value": 6}, {"target": "('Frodo ',)", "source": "('Pippin ',)", "value": 11}, {"target": "('Bolger ',)", "source": "('Pippin ',)", "value": 2}, {"target": "('Legolas ',)", "source": "('Pippin ',)", "value": 3}, {"target": "('Merry ',)", "source": "('Pippin ',)", "value": 21}, {"target": "('Company ',)", "source": "('Pippin ',)", "value": 2}, {"target": "('Folco ',)", "source": "('Pippin ',)", "value": 2}, {"target": "('Bilbo ',)", "source": "('Pippin ',)", "value": 2}, {"target": "('Bilbo ',)", "source": "('Tooks ',)", "value": 2}, {"target": "('Lurien ',)", "source": "('Naith ',)", "value": 2}, {"target": "('Hall ',)", "source": "('Brandy ',)", "value": 4}, {"target": "('Gondor ',)", "source": "('South ',)", "value": 2}, {"target": "('Amroth ',)", "source": "('South ',)", "value": 2}, {"target": "('Road ',)", "source": "('Bridge ',)", "value": 3}, {"target": "('Brandywine ',)", "source": "('Bridge ',)", "value": 2}, {"target": "('White ',)", "source": "('Council ',)", "value": 2}, {"target": "('Bilbo ',)", "source": "('Gollum ',)", "value": 3}, {"target": "('Ford ',)", "source": "('Bruinen ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Gluin ',)", "value": 2}, {"target": "('Legolas ',)", "source": "('Gluin ',)", "value": 2}, {"target": "('Thingol ',)", "source": "('Beren ',)", "value": 2}, {"target": "('Enemy ',)", "source": "('Beren ',)", "value": 2}, {"target": "('Barahir ',)", "source": "('Beren ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('River ',)", "value": 2}, {"target": "('Silverlode ',)", "source": "('River ',)", "value": 2}, {"target": "('Road ',)", "source": "('River ',)", "value": 2}, {"target": "('Lothlurien ',)", "source": "('River ',)", "value": 2}, {"target": "('Wilderland ',)", "source": "('River ',)", "value": 2}, {"target": "('Minas ',)", "source": "('River ',)", "value": 2}, {"target": "('Rauros ',)", "source": "('River ',)", "value": 4}, {"target": "('Company ',)", "source": "('River ',)", "value": 2}, {"target": "('Sarn ',)", "source": "('River ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Baggins ',)", "value": 7}, {"target": "('Shire ',)", "source": "('Baggins ',)", "value": 3}, {"target": "('Hobbiton ',)", "source": "('Baggins ',)", "value": 2}, {"target": "('Bilbo ',)", "source": "('Baggins ',)", "value": 6}, {"target": "('Galadriel ',)", "source": "('Lady ',)", "value": 8}, {"target": "('Lord ',)", "source": "('Lady ',)", "value": 8}, {"target": "('Celeborn ',)", "source": "('Lady ',)", "value": 4}, {"target": "('Galadhrim ',)", "source": "('Lady ',)", "value": 2}, {"target": "('Minas ',)", "source": "('Tirith ',)", "value": 14}, {"target": "('Legolas ',)", "source": "('Gimli ',)", "value": 2}, {"target": "('Gandalf ',)", "source": "('Gimli ',)", "value": 3}, {"target": "('Beside ',)", "source": "('Gimli ',)", "value": 2}, {"target": "('Dimrill ',)", "source": "('Dale ',)", "value": 4}, {"target": "('Book ',)", "source": "('Westmarch ',)", "value": 3}, {"target": "('Isildur ',)", "source": "('Gladden ',)", "value": 2}, {"target": "('Fields ',)", "source": "('Gladden ',)", "value": 3}, {"target": "('Frodo ',)", "source": "('Elrond ',)", "value": 3}, {"target": "('Rivendell ',)", "source": "('Elrond ',)", "value": 2}, {"target": "('Enemy ',)", "source": "('Elrond ',)", "value": 2}, {"target": "('Sauron ',)", "source": "('Elrond ',)", "value": 2}, {"target": "('Elrond ',)", "source": "('Rivendell ',)", "value": 2}, {"target": "('Silverlode ',)", "source": "('Anduin ',)", "value": 2}, {"target": "('Lurien ',)", "source": "('Anduin ',)", "value": 2}, {"target": "('Balin ',)", "source": "('Chamber ',)", "value": 2}, {"target": "('Road ',)", "source": "('Bree ',)", "value": 3}, {"target": "('Shire ',)", "source": "('Bree ',)", "value": 2}, {"target": "('Staddle ',)", "source": "('Bree ',)", "value": 2}, {"target": "('Combe ',)", "source": "('Bree ',)", "value": 2}, {"target": "('Minas ',)", "source": "('Entwash ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Sancho ',)", "value": 2}, {"target": "('Bill ',)", "source": "('Ferny ',)", "value": 3}, {"target": "('Brandywine ',)", "source": "('September ',)", "value": 2}, {"target": "('Beren ',)", "source": "('Thingol ',)", "value": 2}, {"target": "('Enemy ',)", "source": "('Thingol ',)", "value": 2}, {"target": "('Michel ',)", "source": "('Mayor ',)", "value": 2}, {"target": "('Westmarch ',)", "source": "('Book ',)", "value": 3}, {"target": "('Poor ',)", "source": "('Bill ',)", "value": 2}, {"target": "('Ferny ',)", "source": "('Bill ',)", "value": 3}, {"target": "('Gamgee ',)", "source": "('Gaffer ',)", "value": 2}, {"target": "('Gondor ',)", "source": "('Emyn ',)", "value": 2}, {"target": "('Shire ',)", "source": "('West ',)", "value": 2}, {"target": "('Delving ',)", "source": "('White ',)", "value": 2}, {"target": "('Council ',)", "source": "('White ',)", "value": 2}, {"target": "('Michel ',)", "source": "('White ',)", "value": 2}, {"target": "('Minas ',)", "source": "('Ithil ',)", "value": 2}, {"target": "('Beren ',)", "source": "('Enemy ',)", "value": 2}, {"target": "('Elrond ',)", "source": "('Enemy ',)", "value": 2}, {"target": "('Thingol ',)", "source": "('Enemy ',)", "value": 2}, {"target": "('Saruman ',)", "source": "('Enemy ',)", "value": 2}, {"target": "('Amroth ',)", "source": "('Nimrodel ',)", "value": 2}, {"target": "('Bombadil ',)", "source": "('Bright ',)", "value": 2}, {"target": "('Rider ',)", "source": "('Black ',)", "value": 2}, {"target": "('Land ',)", "source": "('Black ',)", "value": 2}, {"target": "('King ',)", "source": "('Dbin ',)", "value": 2}, {"target": "('Chamber ',)", "source": "('Balin ',)", "value": 2}, {"target": "('Prancing ',)", "source": "('Pony ',)", "value": 2}, {"target": "('River ',)", "source": "('Rauros ',)", "value": 4}, {"target": "('Bree ',)", "source": "('Staddle ',)", "value": 2}, {"target": "('Combe ',)", "source": "('Staddle ',)", "value": 2}, {"target": "('Archet ',)", "source": "('Staddle ',)", "value": 2}, {"target": "('Naith ',)", "source": "('Lurien ',)", "value": 2}, {"target": "('Anduin ',)", "source": "('Lurien ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Company ',)", "value": 2}, {"target": "('Haldir ',)", "source": "('Company ',)", "value": 2}, {"target": "('Legolas ',)", "source": "('Company ',)", "value": 3}, {"target": "('Gandalf ',)", "source": "('Company ',)", "value": 2}, {"target": "('Minas ',)", "source": "('Company ',)", "value": 2}, {"target": "('Pippin ',)", "source": "('Company ',)", "value": 2}, {"target": "('River ',)", "source": "('Company ',)", "value": 2}, {"target": "('Aragorn ',)", "source": "('Company ',)", "value": 2}, {"target": "('Downs ',)", "source": "('Brandywine ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Brandywine ',)", "value": 2}, {"target": "('Shire ',)", "source": "('Brandywine ',)", "value": 2}, {"target": "('Bridge ',)", "source": "('Brandywine ',)", "value": 2}, {"target": "('September ',)", "source": "('Brandywine ',)", "value": 2}, {"target": "('Forest ',)", "source": "('Brandywine ',)", "value": 2}, {"target": "('Grey ',)", "source": "('Havens ',)", "value": 2}, {"target": "('Beren ',)", "source": "('Barahir ',)", "value": 2}, {"target": "('Black ',)", "source": "('Rider ',)", "value": 2}, {"target": "('Redhorn ',)", "source": "('Gate ',)", "value": 2}, {"target": "('Gandalf ',)", "source": "('Thorin ',)", "value": 2}, {"target": "('Folk ',)", "source": "('Fair ',)", "value": 2}, {"target": "('Bree ',)", "source": "('Combe ',)", "value": 2}, {"target": "('Staddle ',)", "source": "('Combe ',)", "value": 2}, {"target": "('Archet ',)", "source": "('Combe ',)", "value": 2}, {"target": "('Thrbin ',)", "source": "('Thrur ',)", "value": 2}, {"target": "('Gandalf ',)", "source": "('Grey ',)", "value": 5}, {"target": "('Havens ',)", "source": "('Grey ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Elvish ',)", "value": 2}, {"target": "('Moria ',)", "source": "('Elvish ',)", "value": 2}, {"target": "('Moon ',)", "source": "('Elvish ',)", "value": 2}, {"target": "('Aragorn ',)", "source": "('Elvish ',)", "value": 2}, {"target": "('Fair ',)", "source": "('Folk ',)", "value": 2}, {"target": "('Bywater ',)", "source": "('Hobbiton ',)", "value": 2}, {"target": "('Baggins ',)", "source": "('Hobbiton ',)", "value": 2}, {"target": "('Deal ',)", "source": "('Smjagol ',)", "value": 2}, {"target": "('Farmer ',)", "source": "('Maggot ',)", "value": 2}, {"target": "('Bolger ',)", "source": "('Fatty ',)", "value": 6}, {"target": "('Merry ',)", "source": "('Fatty ',)", "value": 2}, {"target": "('Gate ',)", "source": "('Redhorn ',)", "value": 2}, {"target": "('Bolger ',)", "source": "('Folco ',)", "value": 2}, {"target": "('Merry ',)", "source": "('Folco ',)", "value": 2}, {"target": "('Pippin ',)", "source": "('Folco ',)", "value": 2}, {"target": "('Fredegar ',)", "source": "('Folco ',)", "value": 2}, {"target": "('Galadriel ',)", "source": "('Celeborn ',)", "value": 2}, {"target": "('Lord ',)", "source": "('Celeborn ',)", "value": 2}, {"target": "('Lady ',)", "source": "('Celeborn ',)", "value": 4}, {"target": "('Delving ',)", "source": "('Michel ',)", "value": 5}, {"target": "('Mayor ',)", "source": "('Michel ',)", "value": 2}, {"target": "('White ',)", "source": "('Michel ',)", "value": 2}, {"target": "('Gaffer ',)", "source": "('Gamgee ',)", "value": 2}, {"target": "('Dale ',)", "source": "('Dimrill ',)", "value": 4}, {"target": "('Bolger ',)", "source": "('Fredegar ',)", "value": 2}, {"target": "('Merry ',)", "source": "('Fredegar ',)", "value": 3}, {"target": "('Folco ',)", "source": "('Fredegar ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Aragorn ',)", "value": 8}, {"target": "('Legolas ',)", "source": "('Aragorn ',)", "value": 4}, {"target": "('Merry ',)", "source": "('Aragorn ',)", "value": 2}, {"target": "('Gandalf ',)", "source": "('Aragorn ',)", "value": 5}, {"target": "('Minas ',)", "source": "('Aragorn ',)", "value": 2}, {"target": "('Company ',)", "source": "('Aragorn ',)", "value": 2}, {"target": "('Elvish ',)", "source": "('Aragorn ',)", "value": 2}, {"target": "('Isildur ',)", "source": "('Aragorn ',)", "value": 2}, {"target": "('Boromir ',)", "source": "('Aragorn ',)", "value": 10}, {"target": "('Arathorn ',)", "source": "('Aragorn ',)", "value": 2}, {"target": "('Minas ',)", "source": "('Tower ',)", "value": 2}, {"target": "('Dark ',)", "source": "('Tower ',)", "value": 6}, {"target": "('Enemy ',)", "source": "('Saruman ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Bilbo ',)", "value": 22}, {"target": "('Gandalf ',)", "source": "('Bilbo ',)", "value": 4}, {"target": "('Shire ',)", "source": "('Bilbo ',)", "value": 2}, {"target": "('Pippin ',)", "source": "('Bilbo ',)", "value": 2}, {"target": "('Tooks ',)", "source": "('Bilbo ',)", "value": 2}, {"target": "('Gollum ',)", "source": "('Bilbo ',)", "value": 3}, {"target": "('Baggins ',)", "source": "('Bilbo ',)", "value": 6}, {"target": "('Minas ',)", "source": "('Isildur ',)", "value": 2}, {"target": "('Gladden ',)", "source": "('Isildur ',)", "value": 2}, {"target": "('Aragorn ',)", "source": "('Isildur ',)", "value": 2}, {"target": "('Elendil ',)", "source": "('Isildur ',)", "value": 5}, {"target": "('Frodo ',)", "source": "('Boromir ',)", "value": 2}, {"target": "('Gandalf ',)", "source": "('Boromir ',)", "value": 2}, {"target": "('Minas ',)", "source": "('Boromir ',)", "value": 2}, {"target": "('Aragorn ',)", "source": "('Boromir ',)", "value": 10}, {"target": "('Gimli ',)", "source": "('Beside ',)", "value": 2}, {"target": "('Thrur ',)", "source": "('Thrbin ',)", "value": 2}, {"target": "('Mordor ',)", "source": "('Sauron ',)", "value": 2}, {"target": "('Elrond ',)", "source": "('Sauron ',)", "value": 2}, {"target": "('Elendil ',)", "source": "('Sauron ',)", "value": 3}, {"target": "('Downs ',)", "source": "('Forest ',)", "value": 2}, {"target": "('Brandywine ',)", "source": "('Forest ',)", "value": 2}, {"target": "('Green ',)", "source": "('Dragon ',)", "value": 2}, {"target": "('Gandalf ',)", "source": "('Tell ',)", "value": 2}, {"target": "('Gebir ',)", "source": "('Sarn ',)", "value": 3}, {"target": "('River ',)", "source": "('Sarn ',)", "value": 2}, {"target": "('Loudwater ',)", "source": "('Ford ',)", "value": 2}, {"target": "('Road ',)", "source": "('Ford ',)", "value": 4}, {"target": "('Bruinen ',)", "source": "('Ford ',)", "value": 2}, {"target": "('Lord ',)", "source": "('Galadhrim ',)", "value": 3}, {"target": "('Lady ',)", "source": "('Galadhrim ',)", "value": 2}, {"target": "('Aragorn ',)", "source": "('Arathorn ',)", "value": 2}, {"target": "('Sword ',)", "source": "('Elendil ',)", "value": 2}, {"target": "('Isildur ',)", "source": "('Elendil ',)", "value": 5}, {"target": "('Sauron ',)", "source": "('Elendil ',)", "value": 3}, {"target": "('Frodo ',)", "source": "('Hill ',)", "value": 2}, {"target": "('Mordor ',)", "source": "('Land ',)", "value": 2}, {"target": "('Black ',)", "source": "('Land ',)", "value": 2}, {"target": "('Frodo ',)", "source": "('Drogo ',)", "value": 2}, {"target": "('Gladden ',)", "source": "('Fields ',)", "value": 3}, {"target": "('Master ',)", "source": "('Brandybuck ',)", "value": 3}, {"target": "('Merry ',)", "source": "('Brandybuck ',)", "value": 3}, {"target": "('Staddle ',)", "source": "('Archet ',)", "value": 2}, {"target": "('Combe ',)", "source": "('Archet ',)", "value": 2}], "nodes": [{"id": "('North ',)", "group": 1}, {"id": "('Isildur ',)", "group": 1}, {"id": "('Dragon ',)", "group": 1}, {"id": "('Gladden ',)", "group": 1}, {"id": "('Haldir ',)", "group": 1}, {"id": "('Arathorn ',)", "group": 1}, {"id": "('White ',)", "group": 1}, {"id": "('Enemy ',)", "group": 1}, {"id": "('Barahir ',)", "group": 1}, {"id": "('King ',)", "group": 1}, {"id": "('Bree ',)", "group": 1}, {"id": "('Fields ',)", "group": 1}, {"id": "('Downs ',)", "group": 1}, {"id": "('West ',)", "group": 1}, {"id": "('Rider ',)", "group": 1}, {"id": "('Bilbo ',)", "group": 1}, {"id": "('September ',)", "group": 1}, {"id": "('Gebir ',)", "group": 1}, {"id": "('Moon ',)", "group": 1}, {"id": "('Road ',)", "group": 1}, {"id": "('Folk ',)", "group": 1}, {"id": "('Hall ',)", "group": 1}, {"id": "('Dale ',)", "group": 1}, {"id": "('Sword ',)", "group": 1}, {"id": "('Lord ',)", "group": 1}, {"id": "('Galadriel ',)", "group": 1}, {"id": "('Bright ',)", "group": 1}, {"id": "('Combe ',)", "group": 1}, {"id": "('Lurien ',)", "group": 1}, {"id": "('Westmarch ',)", "group": 1}, {"id": "('Master ',)", "group": 1}, {"id": "('Nimrodel ',)", "group": 1}, {"id": "('Farmer ',)", "group": 1}, {"id": "('Bolger ',)", "group": 1}, {"id": "('Silverlode ',)", "group": 1}, {"id": "('Boromir ',)", "group": 1}, {"id": "('Book ',)", "group": 1}, {"id": "('Mordor ',)", "group": 1}, {"id": "('Lothlurien ',)", "group": 1}, {"id": "('Bombadil ',)", "group": 1}, {"id": "('Brandybuck ',)", "group": 1}, {"id": "('Staddle ',)", "group": 1}, {"id": "('Sauron ',)", "group": 1}, {"id": "('Deal ',)", "group": 1}, {"id": "('Naith ',)", "group": 1}, {"id": "('Moria ',)", "group": 1}, {"id": "('Black ',)", "group": 1}, {"id": "('Thrur ',)", "group": 1}, {"id": "('Havens ',)", "group": 1}, {"id": "('Emyn ',)", "group": 1}, {"id": "('Ithil ',)", "group": 1}, {"id": "('Merry ',)", "group": 1}, {"id": "('Sancho ',)", "group": 1}, {"id": "('Legolas ',)", "group": 1}, {"id": "('Gluin ',)", "group": 1}, {"id": "('Folco ',)", "group": 1}, {"id": "('Forest ',)", "group": 1}, {"id": "('Captain ',)", "group": 1}, {"id": "('Elendil ',)", "group": 1}, {"id": "('Sarn ',)", "group": 1}, {"id": "('Dimrill ',)", "group": 1}, {"id": "('Beside ',)", "group": 1}, {"id": "('Pony ',)", "group": 1}, {"id": "('Thrbin ',)", "group": 1}, {"id": "('Aragorn ',)", "group": 1}, {"id": "('Tell ',)", "group": 1}, {"id": "('Grey ',)", "group": 1}, {"id": "('Entwash ',)", "group": 1}, {"id": "('Elvish ',)", "group": 1}, {"id": "('Redhorn ',)", "group": 1}, {"id": "('Fredegar ',)", "group": 1}, {"id": "('Gaffer ',)", "group": 1}, {"id": "('Chamber ',)", "group": 1}, {"id": "('Delving ',)", "group": 1}, {"id": "('Ferny ',)", "group": 1}, {"id": "('Shire ',)", "group": 1}, {"id": "('Hoarwell ',)", "group": 1}, {"id": "('Bill ',)", "group": 1}, {"id": "('Tooks ',)", "group": 1}, {"id": "('Baggins ',)", "group": 1}, {"id": "('Lady ',)", "group": 1}, {"id": "('Tower ',)", "group": 1}, {"id": "('Hobbiton ',)", "group": 1}, {"id": "('Thingol ',)", "group": 1}, {"id": "('Company ',)", "group": 1}, {"id": "('Frodo ',)", "group": 1}, {"id": "('Gandalf ',)", "group": 1}, {"id": "('River ',)", "group": 1}, {"id": "('Maggot ',)", "group": 1}, {"id": "('Land ',)", "group": 1}, {"id": "('Poor ',)", "group": 1}, {"id": "('Rauros ',)", "group": 1}, {"id": "('Gollum ',)", "group": 1}, {"id": "('Bywater ',)", "group": 1}, {"id": "('Loudwater ',)", "group": 1}, {"id": "('Gate ',)", "group": 1}, {"id": "('Beren ',)", "group": 1}, {"id": "('Gondor ',)", "group": 1}, {"id": "('Gimli ',)", "group": 1}, {"id": "('Anduin ',)", "group": 1}, {"id": "('Celeborn ',)", "group": 1}, {"id": "('Pippin ',)", "group": 1}, {"id": "('Bridge ',)", "group": 1}, {"id": "('Smjagol ',)", "group": 1}, {"id": "('Elrond ',)", "group": 1}, {"id": "('Dark ',)", "group": 1}, {"id": "('Gamgee ',)", "group": 1}, {"id": "('Hill ',)", "group": 1}, {"id": "('Tirith ',)", "group": 1}, {"id": "('Minas ',)", "group": 1}, {"id": "('Glorfindel ',)", "group": 1}, {"id": "('Bruinen ',)", "group": 1}, {"id": "('Balin ',)", "group": 1}, {"id": "('Amroth ',)", "group": 1}, {"id": "('Gildor ',)", "group": 1}, {"id": "('Fair ',)", "group": 1}, {"id": "('Fatty ',)", "group": 1}, {"id": "('Archet ',)", "group": 1}, {"id": "('Barliman ',)", "group": 1}, {"id": "('Drogo ',)", "group": 1}, {"id": "('Cerin ',)", "group": 1}, {"id": "('Galadhrim ',)", "group": 1}, {"id": "('Ford ',)", "group": 1}, {"id": "('Brandy ',)", "group": 1}, {"id": "('Amon ',)", "group": 1}, {"id": "('Rivendell ',)", "group": 1}, {"id": "('Green ',)", "group": 1}, {"id": "('Dbin ',)", "group": 1}, {"id": "('Thorin ',)", "group": 1}, {"id": "('Butterbur ',)", "group": 1}, {"id": "('Wilderland ',)", "group": 1}, {"id": "('Council ',)", "group": 1}, {"id": "('Michel ',)", "group": 1}, {"id": "('Kingdom ',)", "group": 1}, {"id": "('South ',)", "group": 1}, {"id": "('Mayor ',)", "group": 1}, {"id": "('Saruman ',)", "group": 1}, {"id": "('Brandywine ',)", "group": 1}, {"id": "('Prancing ',)", "group": 1}]} -------------------------------------------------------------------------------- /data/processed/bookworm.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [{ 3 | "id": "('miles penn ',)", 4 | "group": 1 5 | }, { 6 | "id": "('caryn vaught ', 'caryn ')", 7 | "group": 1 8 | }, { 9 | "id": "('sharyn vaught ', 'sharyn ')", 10 | "group": 1 11 | }, { 12 | "id": "('ann kittenplan ', 'kittenplan ')", 13 | "group": 1 14 | }, { 15 | "id": "('erica siress ',)", 16 | "group": 1 17 | }, { 18 | "id": "('jennie bash ',)", 19 | "group": 1 20 | }, { 21 | "id": "('amy wingo ',)", 22 | "group": 1 23 | }, { 24 | "id": "('lori clow ',)", 25 | "group": 1 26 | }, { 27 | "id": "('shoshana abrams ',)", 28 | "group": 1 29 | }, { 30 | "id": "('carol spodek ',)", 31 | "group": 1 32 | }, { 33 | "id": "('frances l. unwin ', 'unwin ')", 34 | "group": 1 35 | }, { 36 | "id": "('tina echt ', 'echt ')", 37 | "group": 1 38 | }, { 39 | "id": "('gretchen holt ',)", 40 | "group": 1 41 | }, { 42 | "id": "('jolene criess ',)", 43 | "group": 1 44 | }, { 45 | "id": "('felicity zwieg ', 'zwieg ')", 46 | "group": 1 47 | }, { 48 | "id": "('zoltan csikzentmihalyi ',)", 49 | "group": 1 50 | }, { 51 | "id": "('bernard makulic ',)", 52 | "group": 1 53 | }, { 54 | "id": "('stephan wagenknecht ',)", 55 | "group": 1 56 | }, { 57 | "id": "('jeff wax ',)", 58 | "group": 1 59 | }, { 60 | "id": "('chip sweeny ',)", 61 | "group": 1 62 | }, { 63 | "id": "('todd \"postal weight\" possalthwaite ', 'possalthwaite ', 'postal weight ')", 64 | "group": 1 65 | }, { 66 | "id": "('otis p. lord ', 'lord ')", 67 | "group": 1 68 | }, { 69 | "id": "('esteban reyes ',)", 70 | "group": 1 71 | }, { 72 | "id": "('guglielmo redondo ',)", 73 | "group": 1 74 | }, { 75 | "id": "('eliot kornspan ',)", 76 | "group": 1 77 | }, { 78 | "id": "('cisne ',)", 79 | "group": 1 80 | }, { 81 | "id": "('jeffrey joseph penn ',)", 82 | "group": 1 83 | }, { 84 | "id": "('tim \"sleepy tp\" peterson ', 'peterson ', 'sleepy tp ')", 85 | "group": 1 86 | }, { 87 | "id": "('kieran mckenna ',)", 88 | "group": 1 89 | }, { 90 | "id": "('brian van vleck ', 'van vleck ')", 91 | "group": 1 92 | }, { 93 | "id": "('lamont chu ',)", 94 | "group": 1 95 | }, { 96 | "id": "('audern tallat-kelpsa ',)", 97 | "group": 1 98 | }, { 99 | "id": "('phillip traub ',)", 100 | "group": 1 101 | }, { 102 | "id": "('josh gopnik ',)", 103 | "group": 1 104 | }, { 105 | "id": "('virgilio ',)", 106 | "group": 1 107 | }, { 108 | "id": "('evan ingersoll ', 'ingersoll ')", 109 | "group": 1 110 | }, { 111 | "id": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 112 | "group": 1 113 | }, { 114 | "id": "('kenn blott ',)", 115 | "group": 1 116 | }, { 117 | "id": "('petropolis khan ', 'petropolis ')", 118 | "group": 1 119 | }, { 120 | "id": "('graham \"yard-guard\" rader ', 'yard guard ')", 121 | "group": 1 122 | }, { 123 | "id": "('kent blott ',)", 124 | "group": 1 125 | }, { 126 | "id": "('lyle ',)", 127 | "group": 1 128 | }, { 129 | "id": "('coach kirk white ',)", 130 | "group": 1 131 | }, { 132 | "id": "('dean of admissions ',)", 133 | "group": 1 134 | }, { 135 | "id": "('sirector of composition ',)", 136 | "group": 1 137 | }, { 138 | "id": "('dean of athletic affairs ',)", 139 | "group": 1 140 | }, { 141 | "id": "('dean of academic affairs ',)", 142 | "group": 1 143 | }, { 144 | "id": "('u.s.s millicent kent ',)", 145 | "group": 1 146 | }, { 147 | "id": "('idris \"id\" arslanian ', 'arslanian ')", 148 | "group": 1 149 | }, { 150 | "id": "('peter beak ',)", 151 | "group": 1 152 | }, { 153 | "id": "('carl \"mobes\" whale ',)", 154 | "group": 1 155 | }, { 156 | "id": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 157 | "group": 1 158 | }, { 159 | "id": "('diane prins ',)", 160 | "group": 1 161 | }, { 162 | "id": "('bernadette longley ',)", 163 | "group": 1 164 | }, { 165 | "id": "('kyle d coyle ',)", 166 | "group": 1 167 | }, { 168 | "id": "('keith freer ', 'freer ', 'the viking ')", 169 | "group": 1 170 | }, { 171 | "id": "('john wayne ',)", 172 | "group": 1 173 | }, { 174 | "id": "('james struck ', 'struck ')", 175 | "group": 1 176 | }, { 177 | "id": "('hugh pemberton ', 'pemberton ')", 178 | "group": 1 179 | }, { 180 | "id": "('tall paul shaw ', 'tp shaw ', 'shaw ')", 181 | "group": 1 182 | }, { 183 | "id": "('jim troeltsch ', 'troeltsch ')", 184 | "group": 1 185 | }, { 186 | "id": "('ted schacht ', 'schacht ')", 187 | "group": 1 188 | }, { 189 | "id": "('van slack ',)", 190 | "group": 1 191 | }, { 192 | "id": "('stockhausen ',)", 193 | "group": 1 194 | }, { 195 | "id": "('gloeckner ',)", 196 | "group": 1 197 | }, { 198 | "id": "('bernard wayne ',)", 199 | "group": 1 200 | }, { 201 | "id": "('noreen lace-forche ',)", 202 | "group": 1 203 | }, { 204 | "id": "('maureen hooley ',)", 205 | "group": 1 206 | }, { 207 | "id": "('tom veals ',)", 208 | "group": 1 209 | }, { 210 | "id": "('fully functional phil ',)", 211 | "group": 1 212 | }, { 213 | "id": "('johnny gentle ',)", 214 | "group": 1 215 | }, { 216 | "id": "('mexican president ',)", 217 | "group": 1 218 | }, { 219 | "id": "('canadian president ',)", 220 | "group": 1 221 | }, { 222 | "id": "('rodney tine ', 'rod the god ', 'rodney \"the god\" tine ')", 223 | "group": 1 224 | }, { 225 | "id": "('bridget c. boone ', 'boone ')", 226 | "group": 1 227 | }, { 228 | "id": "('hal ',)", 229 | "group": 1 230 | }, { 231 | "id": "('dymphna ',)", 232 | "group": 1 233 | }, { 234 | "id": "('mario ',)", 235 | "group": 1 236 | }, { 237 | "id": "('schtitt ',)", 238 | "group": 1 239 | }, { 240 | "id": "('poutrincourt ',)", 241 | "group": 1 242 | }, { 243 | "id": "('thode ',)", 244 | "group": 1 245 | }, { 246 | "id": "('ruth ',)", 247 | "group": 1 248 | }, { 249 | "id": "('rik dunkel ',)", 250 | "group": 1 251 | }, { 252 | "id": "('nwangi ',)", 253 | "group": 1 254 | }, { 255 | "id": "('corbett thorp ',)", 256 | "group": 1 257 | }, { 258 | "id": "('cantrell ',)", 259 | "group": 1 260 | }, { 261 | "id": "('donnie scott ',)", 262 | "group": 1 263 | }, { 264 | "id": "('tex watson ',)", 265 | "group": 1 266 | }, { 267 | "id": "('neil hartigan ',)", 268 | "group": 1 269 | }, { 270 | "id": "('delint ',)", 271 | "group": 1 272 | }, { 273 | "id": "('miriam pricket ',)", 274 | "group": 1 275 | }, { 276 | "id": "('flottman ',)", 277 | "group": 1 278 | }, { 279 | "id": "('fentress ',)", 280 | "group": 1 281 | }, { 282 | "id": "('lingley ',)", 283 | "group": 1 284 | }, { 285 | "id": "('pettijohn ',)", 286 | "group": 1 287 | }, { 288 | "id": "('chawaf ',)", 289 | "group": 1 290 | }, { 291 | "id": "('urquhart ',)", 292 | "group": 1 293 | }, { 294 | "id": "('disney r. leith ',)", 295 | "group": 1 296 | }, { 297 | "id": "('melinda ',)", 298 | "group": 1 299 | }, { 300 | "id": "('vogelsong ',)", 301 | "group": 1 302 | }, { 303 | "id": "('rutherford keck ',)", 304 | "group": 1 305 | }, { 306 | "id": "('crosby baum ',)", 307 | "group": 1 308 | }, { 309 | "id": "('reeves mainwaring ',)", 310 | "group": 1 311 | }, { 312 | "id": "('iaccarino ',)", 313 | "group": 1 314 | }, { 315 | "id": "('molly cantrell notkin ', 'notkin ')", 316 | "group": 1 317 | }, { 318 | "id": "('barry loach ', 'loach ')", 319 | "group": 1 320 | }, { 321 | "id": "('the moms ', 'avril ', 'mondragon ')", 322 | "group": 1 323 | }, { 324 | "id": "('pemulis ',)", 325 | "group": 1 326 | }, { 327 | "id": "('dick willis ',)", 328 | "group": 1 329 | }, { 330 | "id": "('thomas m. flatto ',)", 331 | "group": 1 332 | }, { 333 | "id": "('dick desai ',)", 334 | "group": 1 335 | }, { 336 | "id": "('luria perec ', 'luria p ')", 337 | "group": 1 338 | }, { 339 | "id": "('fortier ',)", 340 | "group": 1 341 | }, { 342 | "id": "('broullime ',)", 343 | "group": 1 344 | }, { 345 | "id": "('balbalis ',)", 346 | "group": 1 347 | }, { 348 | "id": "('ossowircke ',)", 349 | "group": 1 350 | }, { 351 | "id": "('beausoleil ',)", 352 | "group": 1 353 | }, { 354 | "id": "('tassigny ',)", 355 | "group": 1 356 | }, { 357 | "id": "('desjardins ',)", 358 | "group": 1 359 | }, { 360 | "id": "('joubet ',)", 361 | "group": 1 362 | }, { 363 | "id": "('harv ',)", 364 | "group": 1 365 | }, { 366 | "id": "('kevin bain ',)", 367 | "group": 1 368 | }, { 369 | "id": "('marlon bain ', 'marlon ')", 370 | "group": 1 371 | }, { 372 | "id": "('henri f. hoyne ', 'henri ')", 373 | "group": 1 374 | }, { 375 | "id": "('miriam hoyne ', 'miriam ')", 376 | "group": 1 377 | }, { 378 | "id": "('steeply ', 'hugh ')", 379 | "group": 1 380 | }, { 381 | "id": "('mo cheery ',)", 382 | "group": 1 383 | }, { 384 | "id": "('muminsky ',)", 385 | "group": 1 386 | }, { 387 | "id": "('orin ',)", 388 | "group": 1 389 | }, { 390 | "id": "('marathe ', 'remy ')", 391 | "group": 1 392 | }, { 393 | "id": "('gertraud ',)", 394 | "group": 1 395 | }, { 396 | "id": "('nickerson ',)", 397 | "group": 1 398 | }, { 399 | "id": "('smothergill ',)", 400 | "group": 1 401 | }, { 402 | "id": "('flechette ',)", 403 | "group": 1 404 | }, { 405 | "id": "('brandeis ',)", 406 | "group": 1 407 | }, { 408 | "id": "('guillaume duplessis ', 'guillaume ', 'duplessis ')", 409 | "group": 1 410 | }, { 411 | "id": "('bertraund ',)", 412 | "group": 1 413 | }, { 414 | "id": "('lucien ',)", 415 | "group": 1 416 | }, { 417 | "id": "('kate gompert ', 'gompert ')", 418 | "group": 1 419 | }, { 420 | "id": "('erdedy ',)", 421 | "group": 1 422 | }, { 423 | "id": "('ruth van cleve ',)", 424 | "group": 1 425 | }, { 426 | "id": "('burt f. smith ', 'burt ')", 427 | "group": 1 428 | }, { 429 | "id": "('poor tony ', 'krause ')", 430 | "group": 1 431 | }, { 432 | "id": "('emil minty ', 'emil ', 'yrstruly ')", 433 | "group": 1 434 | }, { 435 | "id": "('susan t. cheese ',)", 436 | "group": 1 437 | }, { 438 | "id": "('bridget tenderhole ',)", 439 | "group": 1 440 | }, { 441 | "id": "('lolasister ',)", 442 | "group": 1 443 | }, { 444 | "id": "('equus reese ',)", 445 | "group": 1 446 | }, { 447 | "id": "('stokeley \"dark star\" mcnair ', 'stokeley ', 'dark star ', 'darkstar ', 'mcnair ')", 448 | "group": 1 449 | }, { 450 | "id": "('dr wo ',)", 451 | "group": 1 452 | }, { 453 | "id": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 454 | "group": 1 455 | }, { 456 | "id": "('ken johnson ',)", 457 | "group": 1 458 | }, { 459 | "id": "('elizabeth tavis ',)", 460 | "group": 1 461 | }, { 462 | "id": "('lateral ', 'alice moore ')", 463 | "group": 1 464 | }, { 465 | "id": "('charles tavis ', 'tavis ')", 466 | "group": 1 467 | }, { 468 | "id": "('barry loach ',)", 469 | "group": 1 470 | }, { 471 | "id": "('therese ',)", 472 | "group": 1 473 | }, { 474 | "id": "('veach ',)", 475 | "group": 1 476 | }, { 477 | "id": "('slodoban ',)", 478 | "group": 1 479 | }, { 480 | "id": "('rusk ',)", 481 | "group": 1 482 | }, { 483 | "id": "('zegarelli ',)", 484 | "group": 1 485 | }, { 486 | "id": "('kenkle ',)", 487 | "group": 1 488 | }, { 489 | "id": "('fdv ', 'harde ', 'fall down very ')", 490 | "group": 1 491 | }, { 492 | "id": "('brandt ',)", 493 | "group": 1 494 | }, { 495 | "id": "('calvin thrust ',)", 496 | "group": 1 497 | }, { 498 | "id": "('didi neaves ',)", 499 | "group": 1 500 | }, { 501 | "id": "('roy tony ',)", 502 | "group": 1 503 | }, { 504 | "id": "('clenette henderson ',)", 505 | "group": 1 506 | }, { 507 | "id": "('dolores epps ',)", 508 | "group": 1 509 | }, { 510 | "id": "('columbus epps ',)", 511 | "group": 1 512 | }, { 513 | "id": "('doony ', 'glynn ')", 514 | "group": 1 515 | }, { 516 | "id": "('wade mcdade ', 'mcdade ')", 517 | "group": 1 518 | }, { 519 | "id": "('alfonso parias-carbo ', 'parias-carbo ')", 520 | "group": 1 521 | }, { 522 | "id": "('tingley ',)", 523 | "group": 1 524 | }, { 525 | "id": "('april cortelyu ',)", 526 | "group": 1 527 | }, { 528 | "id": "('david krone ',)", 529 | "group": 1 530 | }, { 531 | "id": "('chandler foss ', 'foss ')", 532 | "group": 1 533 | }, { 534 | "id": "('morris hanley ',)", 535 | "group": 1 536 | }, { 537 | "id": "('jennifer belbin ',)", 538 | "group": 1 539 | }, { 540 | "id": "('selwyn ',)", 541 | "group": 1 542 | }, { 543 | "id": "('hester ', 'thrale ')", 544 | "group": 1 545 | }, { 546 | "id": "('kubitz ',)", 547 | "group": 1 548 | }, { 549 | "id": "('nell gunther ',)", 550 | "group": 1 551 | }, { 552 | "id": "('gavin diehl ', 'gavin ', 'diehl ')", 553 | "group": 1 554 | }, { 555 | "id": "('tiny ewell ', 'ewell ')", 556 | "group": 1 557 | }, { 558 | "id": "('montesian ',)", 559 | "group": 1 560 | }, { 561 | "id": "('annie parrot ',)", 562 | "group": 1 563 | }, { 564 | "id": "('mildred bonk green ',)", 565 | "group": 1 566 | }, { 567 | "id": "('bruce green ',)", 568 | "group": 1 569 | }, { 570 | "id": "('foltz ',)", 571 | "group": 1 572 | }, { 573 | "id": "('geoff ', 'geoffrey day ')", 574 | "group": 1 575 | }, { 576 | "id": "('tommy doocey ',)", 577 | "group": 1 578 | }, { 579 | "id": "('yolanda ',)", 580 | "group": 1 581 | }, { 582 | "id": "('randy ', 'lenz ')", 583 | "group": 1 584 | }, { 585 | "id": "('bobby c ',)", 586 | "group": 1 587 | }, { 588 | "id": "('purpleboy ',)", 589 | "group": 1 590 | }, { 591 | "id": "('kely vinoy ',)", 592 | "group": 1 593 | }, { 594 | "id": "('pamela hoffman-jeep ', 'hoffman-jeep ')", 595 | "group": 1 596 | }, { 597 | "id": "('lobokulas ',)", 598 | "group": 1 599 | }, { 600 | "id": "('joelle ', 'van dyne ', 'lucille ')", 601 | "group": 1 602 | }, { 603 | "id": "('lady delphina ',)", 604 | "group": 1 605 | }, { 606 | "id": "('attache ', 'saudi ')", 607 | "group": 1 608 | }, { 609 | "id": "('wraith ',)", 610 | "group": 1 611 | }, { 612 | "id": "('pendleton ',)", 613 | "group": 1 614 | }, { 615 | "id": "('prissburger ',)", 616 | "group": 1 617 | }, { 618 | "id": "('cathy ', 'kathy ')", 619 | "group": 1 620 | }, { 621 | "id": "('glenn ', 'glenn k ')", 622 | "group": 1 623 | }, { 624 | "id": "('bud o ',)", 625 | "group": 1 626 | }, { 627 | "id": "('sven s ',)", 628 | "group": 1 629 | }, { 630 | "id": "('jack j ',)", 631 | "group": 1 632 | }, { 633 | "id": "('dicky n ',)", 634 | "group": 1 635 | }, { 636 | "id": "('tamara n ',)", 637 | "group": 1 638 | }, { 639 | "id": "('louise b ',)", 640 | "group": 1 641 | }, { 642 | "id": "('john l ',)", 643 | "group": 1 644 | }, { 645 | "id": "('ferocious francis ', 'francis ')", 646 | "group": 1 647 | }, { 648 | "id": "('bob death ',)", 649 | "group": 1 650 | }, { 651 | "id": "('whitey sorkin ', 'sorkin ')", 652 | "group": 1 653 | }, { 654 | "id": "('sixties bob ', 'bob monroe ')", 655 | "group": 1 656 | }, { 657 | "id": "('eighties bill ',)", 658 | "group": 1 659 | }, { 660 | "id": "(\"gwendine o'shay \",)", 661 | "group": 1 662 | }, { 663 | "id": "('gately ', 'don ')", 664 | "group": 1 665 | }, { 666 | "id": "('quo vadis ',)", 667 | "group": 1 668 | }, { 669 | "id": "('eugene ', 'fackelmann ')", 670 | "group": 1 671 | }, { 672 | "id": "('martinez ',)", 673 | "group": 1 674 | }, { 675 | "id": "('revere ada ',)", 676 | "group": 1 677 | }, { 678 | "id": "('waite ',)", 679 | "group": 1 680 | }, { 681 | "id": "('sir osis of thuliver ',)", 682 | "group": 1 683 | }], 684 | "links": [{ 685 | "target": "('otis p. lord ', 'lord ')", 686 | "source": "('ann kittenplan ', 'kittenplan ')", 687 | "value": 3 688 | }, { 689 | "target": "('evan ingersoll ', 'ingersoll ')", 690 | "source": "('ann kittenplan ', 'kittenplan ')", 691 | "value": 5 692 | }, { 693 | "target": "('pemulis ',)", 694 | "source": "('ann kittenplan ', 'kittenplan ')", 695 | "value": 5 696 | }, { 697 | "target": "('bridget c. boone ', 'boone ')", 698 | "source": "('frances l. unwin ', 'unwin ')", 699 | "value": 3 700 | }, { 701 | "target": "('stephan wagenknecht ',)", 702 | "source": "('tina echt ', 'echt ')", 703 | "value": 3 704 | }, { 705 | "target": "('tina echt ', 'echt ')", 706 | "source": "('stephan wagenknecht ',)", 707 | "value": 3 708 | }, { 709 | "target": "('hal ',)", 710 | "source": "('todd \"postal weight\" possalthwaite ', 'possalthwaite ', 'postal weight ')", 711 | "value": 3 712 | }, { 713 | "target": "('waite ',)", 714 | "source": "('todd \"postal weight\" possalthwaite ', 'possalthwaite ', 'postal weight ')", 715 | "value": 21 716 | }, { 717 | "target": "('ann kittenplan ', 'kittenplan ')", 718 | "source": "('otis p. lord ', 'lord ')", 719 | "value": 3 720 | }, { 721 | "target": "('evan ingersoll ', 'ingersoll ')", 722 | "source": "('otis p. lord ', 'lord ')", 723 | "value": 7 724 | }, { 725 | "target": "('hal ',)", 726 | "source": "('otis p. lord ', 'lord ')", 727 | "value": 8 728 | }, { 729 | "target": "('pemulis ',)", 730 | "source": "('otis p. lord ', 'lord ')", 731 | "value": 10 732 | }, { 733 | "target": "('lamont chu ',)", 734 | "source": "('tim \"sleepy tp\" peterson ', 'peterson ', 'sleepy tp ')", 735 | "value": 3 736 | }, { 737 | "target": "('tim \"sleepy tp\" peterson ', 'peterson ', 'sleepy tp ')", 738 | "source": "('lamont chu ',)", 739 | "value": 3 740 | }, { 741 | "target": "('ann kittenplan ', 'kittenplan ')", 742 | "source": "('evan ingersoll ', 'ingersoll ')", 743 | "value": 5 744 | }, { 745 | "target": "('otis p. lord ', 'lord ')", 746 | "source": "('evan ingersoll ', 'ingersoll ')", 747 | "value": 7 748 | }, { 749 | "target": "('idris \"id\" arslanian ', 'arslanian ')", 750 | "source": "('evan ingersoll ', 'ingersoll ')", 751 | "value": 3 752 | }, { 753 | "target": "('hal ',)", 754 | "source": "('evan ingersoll ', 'ingersoll ')", 755 | "value": 13 756 | }, { 757 | "target": "('pemulis ',)", 758 | "source": "('evan ingersoll ', 'ingersoll ')", 759 | "value": 8 760 | }, { 761 | "target": "('lyle ',)", 762 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 763 | "value": 5 764 | }, { 765 | "target": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 766 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 767 | "value": 3 768 | }, { 769 | "target": "('keith freer ', 'freer ', 'the viking ')", 770 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 771 | "value": 6 772 | }, { 773 | "target": "('james struck ', 'struck ')", 774 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 775 | "value": 7 776 | }, { 777 | "target": "('tall paul shaw ', 'tp shaw ', 'shaw ')", 778 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 779 | "value": 4 780 | }, { 781 | "target": "('jim troeltsch ', 'troeltsch ')", 782 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 783 | "value": 9 784 | }, { 785 | "target": "('ted schacht ', 'schacht ')", 786 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 787 | "value": 4 788 | }, { 789 | "target": "('hal ',)", 790 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 791 | "value": 49 792 | }, { 793 | "target": "('mario ',)", 794 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 795 | "value": 3 796 | }, { 797 | "target": "('schtitt ',)", 798 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 799 | "value": 7 800 | }, { 801 | "target": "('delint ',)", 802 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 803 | "value": 12 804 | }, { 805 | "target": "('pemulis ',)", 806 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 807 | "value": 13 808 | }, { 809 | "target": "('steeply ', 'hugh ')", 810 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 811 | "value": 5 812 | }, { 813 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 814 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 815 | "value": 3 816 | }, { 817 | "target": "('charles tavis ', 'tavis ')", 818 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 819 | "value": 4 820 | }, { 821 | "target": "('rusk ',)", 822 | "source": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 823 | "value": 3 824 | }, { 825 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 826 | "source": "('lyle ',)", 827 | "value": 5 828 | }, { 829 | "target": "('hal ',)", 830 | "source": "('lyle ',)", 831 | "value": 4 832 | }, { 833 | "target": "('mario ',)", 834 | "source": "('lyle ',)", 835 | "value": 7 836 | }, { 837 | "target": "('pemulis ',)", 838 | "source": "('lyle ',)", 839 | "value": 4 840 | }, { 841 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 842 | "source": "('lyle ',)", 843 | "value": 3 844 | }, { 845 | "target": "('evan ingersoll ', 'ingersoll ')", 846 | "source": "('idris \"id\" arslanian ', 'arslanian ')", 847 | "value": 3 848 | }, { 849 | "target": "('hal ',)", 850 | "source": "('idris \"id\" arslanian ', 'arslanian ')", 851 | "value": 3 852 | }, { 853 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 854 | "source": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 855 | "value": 3 856 | }, { 857 | "target": "('james struck ', 'struck ')", 858 | "source": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 859 | "value": 10 860 | }, { 861 | "target": "('jim troeltsch ', 'troeltsch ')", 862 | "source": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 863 | "value": 7 864 | }, { 865 | "target": "('ted schacht ', 'schacht ')", 866 | "source": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 867 | "value": 4 868 | }, { 869 | "target": "('hal ',)", 870 | "source": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 871 | "value": 21 872 | }, { 873 | "target": "('pemulis ',)", 874 | "source": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 875 | "value": 27 876 | }, { 877 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 878 | "source": "('keith freer ', 'freer ', 'the viking ')", 879 | "value": 6 880 | }, { 881 | "target": "('james struck ', 'struck ')", 882 | "source": "('keith freer ', 'freer ', 'the viking ')", 883 | "value": 8 884 | }, { 885 | "target": "('jim troeltsch ', 'troeltsch ')", 886 | "source": "('keith freer ', 'freer ', 'the viking ')", 887 | "value": 8 888 | }, { 889 | "target": "('hal ',)", 890 | "source": "('keith freer ', 'freer ', 'the viking ')", 891 | "value": 4 892 | }, { 893 | "target": "('pemulis ',)", 894 | "source": "('keith freer ', 'freer ', 'the viking ')", 895 | "value": 18 896 | }, { 897 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 898 | "source": "('james struck ', 'struck ')", 899 | "value": 7 900 | }, { 901 | "target": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 902 | "source": "('james struck ', 'struck ')", 903 | "value": 10 904 | }, { 905 | "target": "('keith freer ', 'freer ', 'the viking ')", 906 | "source": "('james struck ', 'struck ')", 907 | "value": 8 908 | }, { 909 | "target": "('jim troeltsch ', 'troeltsch ')", 910 | "source": "('james struck ', 'struck ')", 911 | "value": 7 912 | }, { 913 | "target": "('bridget c. boone ', 'boone ')", 914 | "source": "('james struck ', 'struck ')", 915 | "value": 5 916 | }, { 917 | "target": "('hal ',)", 918 | "source": "('james struck ', 'struck ')", 919 | "value": 15 920 | }, { 921 | "target": "('mario ',)", 922 | "source": "('james struck ', 'struck ')", 923 | "value": 3 924 | }, { 925 | "target": "('pemulis ',)", 926 | "source": "('james struck ', 'struck ')", 927 | "value": 14 928 | }, { 929 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 930 | "source": "('james struck ', 'struck ')", 931 | "value": 7 932 | }, { 933 | "target": "('gately ', 'don ')", 934 | "source": "('james struck ', 'struck ')", 935 | "value": 3 936 | }, { 937 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 938 | "source": "('tall paul shaw ', 'tp shaw ', 'shaw ')", 939 | "value": 4 940 | }, { 941 | "target": "('pemulis ',)", 942 | "source": "('tall paul shaw ', 'tp shaw ', 'shaw ')", 943 | "value": 3 944 | }, { 945 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 946 | "source": "('jim troeltsch ', 'troeltsch ')", 947 | "value": 9 948 | }, { 949 | "target": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 950 | "source": "('jim troeltsch ', 'troeltsch ')", 951 | "value": 7 952 | }, { 953 | "target": "('keith freer ', 'freer ', 'the viking ')", 954 | "source": "('jim troeltsch ', 'troeltsch ')", 955 | "value": 8 956 | }, { 957 | "target": "('james struck ', 'struck ')", 958 | "source": "('jim troeltsch ', 'troeltsch ')", 959 | "value": 7 960 | }, { 961 | "target": "('ted schacht ', 'schacht ')", 962 | "source": "('jim troeltsch ', 'troeltsch ')", 963 | "value": 5 964 | }, { 965 | "target": "('bridget c. boone ', 'boone ')", 966 | "source": "('jim troeltsch ', 'troeltsch ')", 967 | "value": 3 968 | }, { 969 | "target": "('hal ',)", 970 | "source": "('jim troeltsch ', 'troeltsch ')", 971 | "value": 21 972 | }, { 973 | "target": "('mario ',)", 974 | "source": "('jim troeltsch ', 'troeltsch ')", 975 | "value": 3 976 | }, { 977 | "target": "('delint ',)", 978 | "source": "('jim troeltsch ', 'troeltsch ')", 979 | "value": 3 980 | }, { 981 | "target": "('pemulis ',)", 982 | "source": "('jim troeltsch ', 'troeltsch ')", 983 | "value": 23 984 | }, { 985 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 986 | "source": "('jim troeltsch ', 'troeltsch ')", 987 | "value": 4 988 | }, { 989 | "target": "('lateral ', 'alice moore ')", 990 | "source": "('jim troeltsch ', 'troeltsch ')", 991 | "value": 4 992 | }, { 993 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 994 | "source": "('ted schacht ', 'schacht ')", 995 | "value": 4 996 | }, { 997 | "target": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 998 | "source": "('ted schacht ', 'schacht ')", 999 | "value": 4 1000 | }, { 1001 | "target": "('jim troeltsch ', 'troeltsch ')", 1002 | "source": "('ted schacht ', 'schacht ')", 1003 | "value": 5 1004 | }, { 1005 | "target": "('hal ',)", 1006 | "source": "('ted schacht ', 'schacht ')", 1007 | "value": 11 1008 | }, { 1009 | "target": "('mario ',)", 1010 | "source": "('ted schacht ', 'schacht ')", 1011 | "value": 3 1012 | }, { 1013 | "target": "('pemulis ',)", 1014 | "source": "('ted schacht ', 'schacht ')", 1015 | "value": 14 1016 | }, { 1017 | "target": "('steeply ', 'hugh ')", 1018 | "source": "('rodney tine ', 'rod the god ', 'rodney \"the god\" tine ')", 1019 | "value": 3 1020 | }, { 1021 | "target": "('frances l. unwin ', 'unwin ')", 1022 | "source": "('bridget c. boone ', 'boone ')", 1023 | "value": 3 1024 | }, { 1025 | "target": "('james struck ', 'struck ')", 1026 | "source": "('bridget c. boone ', 'boone ')", 1027 | "value": 5 1028 | }, { 1029 | "target": "('jim troeltsch ', 'troeltsch ')", 1030 | "source": "('bridget c. boone ', 'boone ')", 1031 | "value": 3 1032 | }, { 1033 | "target": "('hal ',)", 1034 | "source": "('bridget c. boone ', 'boone ')", 1035 | "value": 7 1036 | }, { 1037 | "target": "('pemulis ',)", 1038 | "source": "('bridget c. boone ', 'boone ')", 1039 | "value": 3 1040 | }, { 1041 | "target": "('todd \"postal weight\" possalthwaite ', 'possalthwaite ', 'postal weight ')", 1042 | "source": "('hal ',)", 1043 | "value": 3 1044 | }, { 1045 | "target": "('otis p. lord ', 'lord ')", 1046 | "source": "('hal ',)", 1047 | "value": 8 1048 | }, { 1049 | "target": "('evan ingersoll ', 'ingersoll ')", 1050 | "source": "('hal ',)", 1051 | "value": 13 1052 | }, { 1053 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 1054 | "source": "('hal ',)", 1055 | "value": 49 1056 | }, { 1057 | "target": "('lyle ',)", 1058 | "source": "('hal ',)", 1059 | "value": 4 1060 | }, { 1061 | "target": "('idris \"id\" arslanian ', 'arslanian ')", 1062 | "source": "('hal ',)", 1063 | "value": 3 1064 | }, { 1065 | "target": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 1066 | "source": "('hal ',)", 1067 | "value": 21 1068 | }, { 1069 | "target": "('keith freer ', 'freer ', 'the viking ')", 1070 | "source": "('hal ',)", 1071 | "value": 4 1072 | }, { 1073 | "target": "('james struck ', 'struck ')", 1074 | "source": "('hal ',)", 1075 | "value": 15 1076 | }, { 1077 | "target": "('jim troeltsch ', 'troeltsch ')", 1078 | "source": "('hal ',)", 1079 | "value": 21 1080 | }, { 1081 | "target": "('ted schacht ', 'schacht ')", 1082 | "source": "('hal ',)", 1083 | "value": 11 1084 | }, { 1085 | "target": "('bridget c. boone ', 'boone ')", 1086 | "source": "('hal ',)", 1087 | "value": 7 1088 | }, { 1089 | "target": "('mario ',)", 1090 | "source": "('hal ',)", 1091 | "value": 46 1092 | }, { 1093 | "target": "('schtitt ',)", 1094 | "source": "('hal ',)", 1095 | "value": 11 1096 | }, { 1097 | "target": "('poutrincourt ',)", 1098 | "source": "('hal ',)", 1099 | "value": 4 1100 | }, { 1101 | "target": "('thode ',)", 1102 | "source": "('hal ',)", 1103 | "value": 3 1104 | }, { 1105 | "target": "('delint ',)", 1106 | "source": "('hal ',)", 1107 | "value": 15 1108 | }, { 1109 | "target": "('barry loach ', 'loach ')", 1110 | "source": "('hal ',)", 1111 | "value": 3 1112 | }, { 1113 | "target": "('the moms ', 'avril ', 'mondragon ')", 1114 | "source": "('hal ',)", 1115 | "value": 33 1116 | }, { 1117 | "target": "('pemulis ',)", 1118 | "source": "('hal ',)", 1119 | "value": 49 1120 | }, { 1121 | "target": "('kevin bain ',)", 1122 | "source": "('hal ',)", 1123 | "value": 3 1124 | }, { 1125 | "target": "('steeply ', 'hugh ')", 1126 | "source": "('hal ',)", 1127 | "value": 5 1128 | }, { 1129 | "target": "('orin ',)", 1130 | "source": "('hal ',)", 1131 | "value": 22 1132 | }, { 1133 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1134 | "source": "('hal ',)", 1135 | "value": 31 1136 | }, { 1137 | "target": "('charles tavis ', 'tavis ')", 1138 | "source": "('hal ',)", 1139 | "value": 10 1140 | }, { 1141 | "target": "('rusk ',)", 1142 | "source": "('hal ',)", 1143 | "value": 4 1144 | }, { 1145 | "target": "('joelle ', 'van dyne ', 'lucille ')", 1146 | "source": "('hal ',)", 1147 | "value": 3 1148 | }, { 1149 | "target": "('waite ',)", 1150 | "source": "('hal ',)", 1151 | "value": 3 1152 | }, { 1153 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 1154 | "source": "('mario ',)", 1155 | "value": 3 1156 | }, { 1157 | "target": "('lyle ',)", 1158 | "source": "('mario ',)", 1159 | "value": 7 1160 | }, { 1161 | "target": "('james struck ', 'struck ')", 1162 | "source": "('mario ',)", 1163 | "value": 3 1164 | }, { 1165 | "target": "('jim troeltsch ', 'troeltsch ')", 1166 | "source": "('mario ',)", 1167 | "value": 3 1168 | }, { 1169 | "target": "('ted schacht ', 'schacht ')", 1170 | "source": "('mario ',)", 1171 | "value": 3 1172 | }, { 1173 | "target": "('hal ',)", 1174 | "source": "('mario ',)", 1175 | "value": 46 1176 | }, { 1177 | "target": "('schtitt ',)", 1178 | "source": "('mario ',)", 1179 | "value": 12 1180 | }, { 1181 | "target": "('delint ',)", 1182 | "source": "('mario ',)", 1183 | "value": 3 1184 | }, { 1185 | "target": "('the moms ', 'avril ', 'mondragon ')", 1186 | "source": "('mario ',)", 1187 | "value": 25 1188 | }, { 1189 | "target": "('pemulis ',)", 1190 | "source": "('mario ',)", 1191 | "value": 6 1192 | }, { 1193 | "target": "('orin ',)", 1194 | "source": "('mario ',)", 1195 | "value": 16 1196 | }, { 1197 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1198 | "source": "('mario ',)", 1199 | "value": 15 1200 | }, { 1201 | "target": "('lateral ', 'alice moore ')", 1202 | "source": "('mario ',)", 1203 | "value": 3 1204 | }, { 1205 | "target": "('charles tavis ', 'tavis ')", 1206 | "source": "('mario ',)", 1207 | "value": 4 1208 | }, { 1209 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 1210 | "source": "('schtitt ',)", 1211 | "value": 7 1212 | }, { 1213 | "target": "('hal ',)", 1214 | "source": "('schtitt ',)", 1215 | "value": 11 1216 | }, { 1217 | "target": "('mario ',)", 1218 | "source": "('schtitt ',)", 1219 | "value": 12 1220 | }, { 1221 | "target": "('thode ',)", 1222 | "source": "('schtitt ',)", 1223 | "value": 3 1224 | }, { 1225 | "target": "('delint ',)", 1226 | "source": "('schtitt ',)", 1227 | "value": 11 1228 | }, { 1229 | "target": "('the moms ', 'avril ', 'mondragon ')", 1230 | "source": "('schtitt ',)", 1231 | "value": 3 1232 | }, { 1233 | "target": "('orin ',)", 1234 | "source": "('schtitt ',)", 1235 | "value": 3 1236 | }, { 1237 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1238 | "source": "('schtitt ',)", 1239 | "value": 6 1240 | }, { 1241 | "target": "('charles tavis ', 'tavis ')", 1242 | "source": "('schtitt ',)", 1243 | "value": 6 1244 | }, { 1245 | "target": "('hal ',)", 1246 | "source": "('poutrincourt ',)", 1247 | "value": 4 1248 | }, { 1249 | "target": "('delint ',)", 1250 | "source": "('poutrincourt ',)", 1251 | "value": 4 1252 | }, { 1253 | "target": "('steeply ', 'hugh ')", 1254 | "source": "('poutrincourt ',)", 1255 | "value": 4 1256 | }, { 1257 | "target": "('hal ',)", 1258 | "source": "('thode ',)", 1259 | "value": 3 1260 | }, { 1261 | "target": "('schtitt ',)", 1262 | "source": "('thode ',)", 1263 | "value": 3 1264 | }, { 1265 | "target": "('kate gompert ', 'gompert ')", 1266 | "source": "('ruth ',)", 1267 | "value": 9 1268 | }, { 1269 | "target": "('ruth van cleve ',)", 1270 | "source": "('ruth ',)", 1271 | "value": 11 1272 | }, { 1273 | "target": "('joelle ', 'van dyne ', 'lucille ')", 1274 | "source": "('ruth ',)", 1275 | "value": 3 1276 | }, { 1277 | "target": "('gately ', 'don ')", 1278 | "source": "('ruth ',)", 1279 | "value": 3 1280 | }, { 1281 | "target": "('delint ',)", 1282 | "source": "('nwangi ',)", 1283 | "value": 4 1284 | }, { 1285 | "target": "('charles tavis ', 'tavis ')", 1286 | "source": "('nwangi ',)", 1287 | "value": 3 1288 | }, { 1289 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 1290 | "source": "('delint ',)", 1291 | "value": 12 1292 | }, { 1293 | "target": "('jim troeltsch ', 'troeltsch ')", 1294 | "source": "('delint ',)", 1295 | "value": 3 1296 | }, { 1297 | "target": "('hal ',)", 1298 | "source": "('delint ',)", 1299 | "value": 15 1300 | }, { 1301 | "target": "('mario ',)", 1302 | "source": "('delint ',)", 1303 | "value": 3 1304 | }, { 1305 | "target": "('schtitt ',)", 1306 | "source": "('delint ',)", 1307 | "value": 11 1308 | }, { 1309 | "target": "('poutrincourt ',)", 1310 | "source": "('delint ',)", 1311 | "value": 4 1312 | }, { 1313 | "target": "('nwangi ',)", 1314 | "source": "('delint ',)", 1315 | "value": 4 1316 | }, { 1317 | "target": "('pemulis ',)", 1318 | "source": "('delint ',)", 1319 | "value": 6 1320 | }, { 1321 | "target": "('steeply ', 'hugh ')", 1322 | "source": "('delint ',)", 1323 | "value": 8 1324 | }, { 1325 | "target": "('orin ',)", 1326 | "source": "('delint ',)", 1327 | "value": 3 1328 | }, { 1329 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1330 | "source": "('delint ',)", 1331 | "value": 3 1332 | }, { 1333 | "target": "('charles tavis ', 'tavis ')", 1334 | "source": "('delint ',)", 1335 | "value": 4 1336 | }, { 1337 | "target": "('joelle ', 'van dyne ', 'lucille ')", 1338 | "source": "('molly cantrell notkin ', 'notkin ')", 1339 | "value": 3 1340 | }, { 1341 | "target": "('hal ',)", 1342 | "source": "('barry loach ', 'loach ')", 1343 | "value": 3 1344 | }, { 1345 | "target": "('barry loach ',)", 1346 | "source": "('barry loach ', 'loach ')", 1347 | "value": 17 1348 | }, { 1349 | "target": "('hal ',)", 1350 | "source": "('the moms ', 'avril ', 'mondragon ')", 1351 | "value": 33 1352 | }, { 1353 | "target": "('mario ',)", 1354 | "source": "('the moms ', 'avril ', 'mondragon ')", 1355 | "value": 25 1356 | }, { 1357 | "target": "('schtitt ',)", 1358 | "source": "('the moms ', 'avril ', 'mondragon ')", 1359 | "value": 3 1360 | }, { 1361 | "target": "('pemulis ',)", 1362 | "source": "('the moms ', 'avril ', 'mondragon ')", 1363 | "value": 5 1364 | }, { 1365 | "target": "('orin ',)", 1366 | "source": "('the moms ', 'avril ', 'mondragon ')", 1367 | "value": 23 1368 | }, { 1369 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1370 | "source": "('the moms ', 'avril ', 'mondragon ')", 1371 | "value": 16 1372 | }, { 1373 | "target": "('charles tavis ', 'tavis ')", 1374 | "source": "('the moms ', 'avril ', 'mondragon ')", 1375 | "value": 7 1376 | }, { 1377 | "target": "('rusk ',)", 1378 | "source": "('the moms ', 'avril ', 'mondragon ')", 1379 | "value": 8 1380 | }, { 1381 | "target": "('joelle ', 'van dyne ', 'lucille ')", 1382 | "source": "('the moms ', 'avril ', 'mondragon ')", 1383 | "value": 11 1384 | }, { 1385 | "target": "('ann kittenplan ', 'kittenplan ')", 1386 | "source": "('pemulis ',)", 1387 | "value": 5 1388 | }, { 1389 | "target": "('otis p. lord ', 'lord ')", 1390 | "source": "('pemulis ',)", 1391 | "value": 10 1392 | }, { 1393 | "target": "('evan ingersoll ', 'ingersoll ')", 1394 | "source": "('pemulis ',)", 1395 | "value": 8 1396 | }, { 1397 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 1398 | "source": "('pemulis ',)", 1399 | "value": 13 1400 | }, { 1401 | "target": "('lyle ',)", 1402 | "source": "('pemulis ',)", 1403 | "value": 4 1404 | }, { 1405 | "target": "('trevor \"axhandle\" axford ', 'axford ', 'axhandle ')", 1406 | "source": "('pemulis ',)", 1407 | "value": 27 1408 | }, { 1409 | "target": "('keith freer ', 'freer ', 'the viking ')", 1410 | "source": "('pemulis ',)", 1411 | "value": 18 1412 | }, { 1413 | "target": "('james struck ', 'struck ')", 1414 | "source": "('pemulis ',)", 1415 | "value": 14 1416 | }, { 1417 | "target": "('tall paul shaw ', 'tp shaw ', 'shaw ')", 1418 | "source": "('pemulis ',)", 1419 | "value": 3 1420 | }, { 1421 | "target": "('jim troeltsch ', 'troeltsch ')", 1422 | "source": "('pemulis ',)", 1423 | "value": 23 1424 | }, { 1425 | "target": "('ted schacht ', 'schacht ')", 1426 | "source": "('pemulis ',)", 1427 | "value": 14 1428 | }, { 1429 | "target": "('bridget c. boone ', 'boone ')", 1430 | "source": "('pemulis ',)", 1431 | "value": 3 1432 | }, { 1433 | "target": "('hal ',)", 1434 | "source": "('pemulis ',)", 1435 | "value": 49 1436 | }, { 1437 | "target": "('mario ',)", 1438 | "source": "('pemulis ',)", 1439 | "value": 6 1440 | }, { 1441 | "target": "('delint ',)", 1442 | "source": "('pemulis ',)", 1443 | "value": 6 1444 | }, { 1445 | "target": "('the moms ', 'avril ', 'mondragon ')", 1446 | "source": "('pemulis ',)", 1447 | "value": 5 1448 | }, { 1449 | "target": "('orin ',)", 1450 | "source": "('pemulis ',)", 1451 | "value": 3 1452 | }, { 1453 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1454 | "source": "('pemulis ',)", 1455 | "value": 12 1456 | }, { 1457 | "target": "('lateral ', 'alice moore ')", 1458 | "source": "('pemulis ',)", 1459 | "value": 3 1460 | }, { 1461 | "target": "('charles tavis ', 'tavis ')", 1462 | "source": "('pemulis ',)", 1463 | "value": 10 1464 | }, { 1465 | "target": "('rusk ',)", 1466 | "source": "('pemulis ',)", 1467 | "value": 5 1468 | }, { 1469 | "target": "('steeply ', 'hugh ')", 1470 | "source": "('fortier ',)", 1471 | "value": 7 1472 | }, { 1473 | "target": "('marathe ', 'remy ')", 1474 | "source": "('fortier ',)", 1475 | "value": 19 1476 | }, { 1477 | "target": "('hal ',)", 1478 | "source": "('kevin bain ',)", 1479 | "value": 3 1480 | }, { 1481 | "target": "('orin ',)", 1482 | "source": "('marlon bain ', 'marlon ')", 1483 | "value": 3 1484 | }, { 1485 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 1486 | "source": "('steeply ', 'hugh ')", 1487 | "value": 5 1488 | }, { 1489 | "target": "('rodney tine ', 'rod the god ', 'rodney \"the god\" tine ')", 1490 | "source": "('steeply ', 'hugh ')", 1491 | "value": 3 1492 | }, { 1493 | "target": "('hal ',)", 1494 | "source": "('steeply ', 'hugh ')", 1495 | "value": 5 1496 | }, { 1497 | "target": "('poutrincourt ',)", 1498 | "source": "('steeply ', 'hugh ')", 1499 | "value": 4 1500 | }, { 1501 | "target": "('delint ',)", 1502 | "source": "('steeply ', 'hugh ')", 1503 | "value": 8 1504 | }, { 1505 | "target": "('fortier ',)", 1506 | "source": "('steeply ', 'hugh ')", 1507 | "value": 7 1508 | }, { 1509 | "target": "('marathe ', 'remy ')", 1510 | "source": "('steeply ', 'hugh ')", 1511 | "value": 82 1512 | }, { 1513 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1514 | "source": "('steeply ', 'hugh ')", 1515 | "value": 12 1516 | }, { 1517 | "target": "('hal ',)", 1518 | "source": "('orin ',)", 1519 | "value": 22 1520 | }, { 1521 | "target": "('mario ',)", 1522 | "source": "('orin ',)", 1523 | "value": 16 1524 | }, { 1525 | "target": "('schtitt ',)", 1526 | "source": "('orin ',)", 1527 | "value": 3 1528 | }, { 1529 | "target": "('delint ',)", 1530 | "source": "('orin ',)", 1531 | "value": 3 1532 | }, { 1533 | "target": "('the moms ', 'avril ', 'mondragon ')", 1534 | "source": "('orin ',)", 1535 | "value": 23 1536 | }, { 1537 | "target": "('pemulis ',)", 1538 | "source": "('orin ',)", 1539 | "value": 3 1540 | }, { 1541 | "target": "('marlon bain ', 'marlon ')", 1542 | "source": "('orin ',)", 1543 | "value": 3 1544 | }, { 1545 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1546 | "source": "('orin ',)", 1547 | "value": 37 1548 | }, { 1549 | "target": "('charles tavis ', 'tavis ')", 1550 | "source": "('orin ',)", 1551 | "value": 3 1552 | }, { 1553 | "target": "('joelle ', 'van dyne ', 'lucille ')", 1554 | "source": "('orin ',)", 1555 | "value": 33 1556 | }, { 1557 | "target": "('fortier ',)", 1558 | "source": "('marathe ', 'remy ')", 1559 | "value": 19 1560 | }, { 1561 | "target": "('steeply ', 'hugh ')", 1562 | "source": "('marathe ', 'remy ')", 1563 | "value": 82 1564 | }, { 1565 | "target": "('guillaume duplessis ', 'guillaume ', 'duplessis ')", 1566 | "source": "('marathe ', 'remy ')", 1567 | "value": 4 1568 | }, { 1569 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1570 | "source": "('marathe ', 'remy ')", 1571 | "value": 15 1572 | }, { 1573 | "target": "('marathe ', 'remy ')", 1574 | "source": "('guillaume duplessis ', 'guillaume ', 'duplessis ')", 1575 | "value": 4 1576 | }, { 1577 | "target": "('lucien ',)", 1578 | "source": "('bertraund ',)", 1579 | "value": 4 1580 | }, { 1581 | "target": "('bertraund ',)", 1582 | "source": "('lucien ',)", 1583 | "value": 4 1584 | }, { 1585 | "target": "('ruth ',)", 1586 | "source": "('kate gompert ', 'gompert ')", 1587 | "value": 9 1588 | }, { 1589 | "target": "('erdedy ',)", 1590 | "source": "('kate gompert ', 'gompert ')", 1591 | "value": 6 1592 | }, { 1593 | "target": "('ruth van cleve ',)", 1594 | "source": "('kate gompert ', 'gompert ')", 1595 | "value": 6 1596 | }, { 1597 | "target": "('kate gompert ', 'gompert ')", 1598 | "source": "('erdedy ',)", 1599 | "value": 6 1600 | }, { 1601 | "target": "('foltz ',)", 1602 | "source": "('erdedy ',)", 1603 | "value": 3 1604 | }, { 1605 | "target": "('randy ', 'lenz ')", 1606 | "source": "('erdedy ',)", 1607 | "value": 3 1608 | }, { 1609 | "target": "('joelle ', 'van dyne ', 'lucille ')", 1610 | "source": "('erdedy ',)", 1611 | "value": 5 1612 | }, { 1613 | "target": "('gately ', 'don ')", 1614 | "source": "('erdedy ',)", 1615 | "value": 5 1616 | }, { 1617 | "target": "('ruth ',)", 1618 | "source": "('ruth van cleve ',)", 1619 | "value": 11 1620 | }, { 1621 | "target": "('kate gompert ', 'gompert ')", 1622 | "source": "('ruth van cleve ',)", 1623 | "value": 6 1624 | }, { 1625 | "target": "('randy ', 'lenz ')", 1626 | "source": "('burt f. smith ', 'burt ')", 1627 | "value": 3 1628 | }, { 1629 | "target": "('emil minty ', 'emil ', 'yrstruly ')", 1630 | "source": "('poor tony ', 'krause ')", 1631 | "value": 13 1632 | }, { 1633 | "target": "('susan t. cheese ',)", 1634 | "source": "('poor tony ', 'krause ')", 1635 | "value": 4 1636 | }, { 1637 | "target": "('poor tony ', 'krause ')", 1638 | "source": "('emil minty ', 'emil ', 'yrstruly ')", 1639 | "value": 13 1640 | }, { 1641 | "target": "('poor tony ', 'krause ')", 1642 | "source": "('susan t. cheese ',)", 1643 | "value": 4 1644 | }, { 1645 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 1646 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1647 | "value": 3 1648 | }, { 1649 | "target": "('lyle ',)", 1650 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1651 | "value": 3 1652 | }, { 1653 | "target": "('james struck ', 'struck ')", 1654 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1655 | "value": 7 1656 | }, { 1657 | "target": "('jim troeltsch ', 'troeltsch ')", 1658 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1659 | "value": 4 1660 | }, { 1661 | "target": "('hal ',)", 1662 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1663 | "value": 31 1664 | }, { 1665 | "target": "('mario ',)", 1666 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1667 | "value": 15 1668 | }, { 1669 | "target": "('schtitt ',)", 1670 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1671 | "value": 6 1672 | }, { 1673 | "target": "('delint ',)", 1674 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1675 | "value": 3 1676 | }, { 1677 | "target": "('the moms ', 'avril ', 'mondragon ')", 1678 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1679 | "value": 16 1680 | }, { 1681 | "target": "('pemulis ',)", 1682 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1683 | "value": 12 1684 | }, { 1685 | "target": "('steeply ', 'hugh ')", 1686 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1687 | "value": 12 1688 | }, { 1689 | "target": "('orin ',)", 1690 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1691 | "value": 37 1692 | }, { 1693 | "target": "('marathe ', 'remy ')", 1694 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1695 | "value": 15 1696 | }, { 1697 | "target": "('charles tavis ', 'tavis ')", 1698 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1699 | "value": 4 1700 | }, { 1701 | "target": "('kenkle ',)", 1702 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1703 | "value": 3 1704 | }, { 1705 | "target": "('brandt ',)", 1706 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1707 | "value": 3 1708 | }, { 1709 | "target": "('montesian ',)", 1710 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1711 | "value": 3 1712 | }, { 1713 | "target": "('randy ', 'lenz ')", 1714 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1715 | "value": 8 1716 | }, { 1717 | "target": "('joelle ', 'van dyne ', 'lucille ')", 1718 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1719 | "value": 10 1720 | }, { 1721 | "target": "('wraith ',)", 1722 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1723 | "value": 5 1724 | }, { 1725 | "target": "('gately ', 'don ')", 1726 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1727 | "value": 39 1728 | }, { 1729 | "target": "('eugene ', 'fackelmann ')", 1730 | "source": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1731 | "value": 5 1732 | }, { 1733 | "target": "('jim troeltsch ', 'troeltsch ')", 1734 | "source": "('lateral ', 'alice moore ')", 1735 | "value": 4 1736 | }, { 1737 | "target": "('mario ',)", 1738 | "source": "('lateral ', 'alice moore ')", 1739 | "value": 3 1740 | }, { 1741 | "target": "('pemulis ',)", 1742 | "source": "('lateral ', 'alice moore ')", 1743 | "value": 3 1744 | }, { 1745 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 1746 | "source": "('charles tavis ', 'tavis ')", 1747 | "value": 4 1748 | }, { 1749 | "target": "('hal ',)", 1750 | "source": "('charles tavis ', 'tavis ')", 1751 | "value": 10 1752 | }, { 1753 | "target": "('mario ',)", 1754 | "source": "('charles tavis ', 'tavis ')", 1755 | "value": 4 1756 | }, { 1757 | "target": "('schtitt ',)", 1758 | "source": "('charles tavis ', 'tavis ')", 1759 | "value": 6 1760 | }, { 1761 | "target": "('nwangi ',)", 1762 | "source": "('charles tavis ', 'tavis ')", 1763 | "value": 3 1764 | }, { 1765 | "target": "('delint ',)", 1766 | "source": "('charles tavis ', 'tavis ')", 1767 | "value": 4 1768 | }, { 1769 | "target": "('the moms ', 'avril ', 'mondragon ')", 1770 | "source": "('charles tavis ', 'tavis ')", 1771 | "value": 7 1772 | }, { 1773 | "target": "('pemulis ',)", 1774 | "source": "('charles tavis ', 'tavis ')", 1775 | "value": 10 1776 | }, { 1777 | "target": "('orin ',)", 1778 | "source": "('charles tavis ', 'tavis ')", 1779 | "value": 3 1780 | }, { 1781 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1782 | "source": "('charles tavis ', 'tavis ')", 1783 | "value": 4 1784 | }, { 1785 | "target": "('barry loach ', 'loach ')", 1786 | "source": "('barry loach ',)", 1787 | "value": 17 1788 | }, { 1789 | "target": "('ortho \"the darkness\" stice ', 'stice ', 'ortho ', 'the darkness ')", 1790 | "source": "('rusk ',)", 1791 | "value": 3 1792 | }, { 1793 | "target": "('hal ',)", 1794 | "source": "('rusk ',)", 1795 | "value": 4 1796 | }, { 1797 | "target": "('the moms ', 'avril ', 'mondragon ')", 1798 | "source": "('rusk ',)", 1799 | "value": 8 1800 | }, { 1801 | "target": "('pemulis ',)", 1802 | "source": "('rusk ',)", 1803 | "value": 5 1804 | }, { 1805 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1806 | "source": "('kenkle ',)", 1807 | "value": 3 1808 | }, { 1809 | "target": "('brandt ',)", 1810 | "source": "('kenkle ',)", 1811 | "value": 13 1812 | }, { 1813 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1814 | "source": "('brandt ',)", 1815 | "value": 3 1816 | }, { 1817 | "target": "('kenkle ',)", 1818 | "source": "('brandt ',)", 1819 | "value": 13 1820 | }, { 1821 | "target": "('wade mcdade ', 'mcdade ')", 1822 | "source": "('doony ', 'glynn ')", 1823 | "value": 4 1824 | }, { 1825 | "target": "('gavin diehl ', 'gavin ', 'diehl ')", 1826 | "source": "('doony ', 'glynn ')", 1827 | "value": 3 1828 | }, { 1829 | "target": "('gately ', 'don ')", 1830 | "source": "('doony ', 'glynn ')", 1831 | "value": 5 1832 | }, { 1833 | "target": "('doony ', 'glynn ')", 1834 | "source": "('wade mcdade ', 'mcdade ')", 1835 | "value": 4 1836 | }, { 1837 | "target": "('gavin diehl ', 'gavin ', 'diehl ')", 1838 | "source": "('wade mcdade ', 'mcdade ')", 1839 | "value": 5 1840 | }, { 1841 | "target": "('randy ', 'lenz ')", 1842 | "source": "('wade mcdade ', 'mcdade ')", 1843 | "value": 4 1844 | }, { 1845 | "target": "('joelle ', 'van dyne ', 'lucille ')", 1846 | "source": "('wade mcdade ', 'mcdade ')", 1847 | "value": 3 1848 | }, { 1849 | "target": "('gately ', 'don ')", 1850 | "source": "('wade mcdade ', 'mcdade ')", 1851 | "value": 5 1852 | }, { 1853 | "target": "('gately ', 'don ')", 1854 | "source": "('chandler foss ', 'foss ')", 1855 | "value": 4 1856 | }, { 1857 | "target": "('randy ', 'lenz ')", 1858 | "source": "('hester ', 'thrale ')", 1859 | "value": 3 1860 | }, { 1861 | "target": "('gately ', 'don ')", 1862 | "source": "('hester ', 'thrale ')", 1863 | "value": 6 1864 | }, { 1865 | "target": "('doony ', 'glynn ')", 1866 | "source": "('gavin diehl ', 'gavin ', 'diehl ')", 1867 | "value": 3 1868 | }, { 1869 | "target": "('wade mcdade ', 'mcdade ')", 1870 | "source": "('gavin diehl ', 'gavin ', 'diehl ')", 1871 | "value": 5 1872 | }, { 1873 | "target": "('gately ', 'don ')", 1874 | "source": "('gavin diehl ', 'gavin ', 'diehl ')", 1875 | "value": 4 1876 | }, { 1877 | "target": "('gately ', 'don ')", 1878 | "source": "('tiny ewell ', 'ewell ')", 1879 | "value": 14 1880 | }, { 1881 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1882 | "source": "('montesian ',)", 1883 | "value": 3 1884 | }, { 1885 | "target": "('gately ', 'don ')", 1886 | "source": "('montesian ',)", 1887 | "value": 5 1888 | }, { 1889 | "target": "('randy ', 'lenz ')", 1890 | "source": "('bruce green ',)", 1891 | "value": 9 1892 | }, { 1893 | "target": "('gately ', 'don ')", 1894 | "source": "('bruce green ',)", 1895 | "value": 4 1896 | }, { 1897 | "target": "('erdedy ',)", 1898 | "source": "('foltz ',)", 1899 | "value": 3 1900 | }, { 1901 | "target": "('erdedy ',)", 1902 | "source": "('randy ', 'lenz ')", 1903 | "value": 3 1904 | }, { 1905 | "target": "('burt f. smith ', 'burt ')", 1906 | "source": "('randy ', 'lenz ')", 1907 | "value": 3 1908 | }, { 1909 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1910 | "source": "('randy ', 'lenz ')", 1911 | "value": 8 1912 | }, { 1913 | "target": "('wade mcdade ', 'mcdade ')", 1914 | "source": "('randy ', 'lenz ')", 1915 | "value": 4 1916 | }, { 1917 | "target": "('hester ', 'thrale ')", 1918 | "source": "('randy ', 'lenz ')", 1919 | "value": 3 1920 | }, { 1921 | "target": "('bruce green ',)", 1922 | "source": "('randy ', 'lenz ')", 1923 | "value": 9 1924 | }, { 1925 | "target": "('gately ', 'don ')", 1926 | "source": "('randy ', 'lenz ')", 1927 | "value": 26 1928 | }, { 1929 | "target": "('gately ', 'don ')", 1930 | "source": "('bobby c ',)", 1931 | "value": 7 1932 | }, { 1933 | "target": "('eugene ', 'fackelmann ')", 1934 | "source": "('bobby c ',)", 1935 | "value": 4 1936 | }, { 1937 | "target": "('gately ', 'don ')", 1938 | "source": "('pamela hoffman-jeep ', 'hoffman-jeep ')", 1939 | "value": 8 1940 | }, { 1941 | "target": "('eugene ', 'fackelmann ')", 1942 | "source": "('pamela hoffman-jeep ', 'hoffman-jeep ')", 1943 | "value": 3 1944 | }, { 1945 | "target": "('hal ',)", 1946 | "source": "('joelle ', 'van dyne ', 'lucille ')", 1947 | "value": 3 1948 | }, { 1949 | "target": "('ruth ',)", 1950 | "source": "('joelle ', 'van dyne ', 'lucille ')", 1951 | "value": 3 1952 | }, { 1953 | "target": "('molly cantrell notkin ', 'notkin ')", 1954 | "source": "('joelle ', 'van dyne ', 'lucille ')", 1955 | "value": 3 1956 | }, { 1957 | "target": "('the moms ', 'avril ', 'mondragon ')", 1958 | "source": "('joelle ', 'van dyne ', 'lucille ')", 1959 | "value": 11 1960 | }, { 1961 | "target": "('orin ',)", 1962 | "source": "('joelle ', 'van dyne ', 'lucille ')", 1963 | "value": 33 1964 | }, { 1965 | "target": "('erdedy ',)", 1966 | "source": "('joelle ', 'van dyne ', 'lucille ')", 1967 | "value": 5 1968 | }, { 1969 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1970 | "source": "('joelle ', 'van dyne ', 'lucille ')", 1971 | "value": 10 1972 | }, { 1973 | "target": "('wade mcdade ', 'mcdade ')", 1974 | "source": "('joelle ', 'van dyne ', 'lucille ')", 1975 | "value": 3 1976 | }, { 1977 | "target": "('gately ', 'don ')", 1978 | "source": "('joelle ', 'van dyne ', 'lucille ')", 1979 | "value": 24 1980 | }, { 1981 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 1982 | "source": "('wraith ',)", 1983 | "value": 5 1984 | }, { 1985 | "target": "('gately ', 'don ')", 1986 | "source": "('wraith ',)", 1987 | "value": 20 1988 | }, { 1989 | "target": "('gately ', 'don ')", 1990 | "source": "('glenn ', 'glenn k ')", 1991 | "value": 3 1992 | }, { 1993 | "target": "('gately ', 'don ')", 1994 | "source": "('ferocious francis ', 'francis ')", 1995 | "value": 12 1996 | }, { 1997 | "target": "('eighties bill ',)", 1998 | "source": "('whitey sorkin ', 'sorkin ')", 1999 | "value": 5 2000 | }, { 2001 | "target": "('gately ', 'don ')", 2002 | "source": "('whitey sorkin ', 'sorkin ')", 2003 | "value": 13 2004 | }, { 2005 | "target": "('eugene ', 'fackelmann ')", 2006 | "source": "('whitey sorkin ', 'sorkin ')", 2007 | "value": 10 2008 | }, { 2009 | "target": "('whitey sorkin ', 'sorkin ')", 2010 | "source": "('eighties bill ',)", 2011 | "value": 5 2012 | }, { 2013 | "target": "('eugene ', 'fackelmann ')", 2014 | "source": "('eighties bill ',)", 2015 | "value": 3 2016 | }, { 2017 | "target": "('james struck ', 'struck ')", 2018 | "source": "('gately ', 'don ')", 2019 | "value": 3 2020 | }, { 2021 | "target": "('ruth ',)", 2022 | "source": "('gately ', 'don ')", 2023 | "value": 3 2024 | }, { 2025 | "target": "('erdedy ',)", 2026 | "source": "('gately ', 'don ')", 2027 | "value": 5 2028 | }, { 2029 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 2030 | "source": "('gately ', 'don ')", 2031 | "value": 39 2032 | }, { 2033 | "target": "('doony ', 'glynn ')", 2034 | "source": "('gately ', 'don ')", 2035 | "value": 5 2036 | }, { 2037 | "target": "('wade mcdade ', 'mcdade ')", 2038 | "source": "('gately ', 'don ')", 2039 | "value": 5 2040 | }, { 2041 | "target": "('chandler foss ', 'foss ')", 2042 | "source": "('gately ', 'don ')", 2043 | "value": 4 2044 | }, { 2045 | "target": "('hester ', 'thrale ')", 2046 | "source": "('gately ', 'don ')", 2047 | "value": 6 2048 | }, { 2049 | "target": "('gavin diehl ', 'gavin ', 'diehl ')", 2050 | "source": "('gately ', 'don ')", 2051 | "value": 4 2052 | }, { 2053 | "target": "('tiny ewell ', 'ewell ')", 2054 | "source": "('gately ', 'don ')", 2055 | "value": 14 2056 | }, { 2057 | "target": "('montesian ',)", 2058 | "source": "('gately ', 'don ')", 2059 | "value": 5 2060 | }, { 2061 | "target": "('bruce green ',)", 2062 | "source": "('gately ', 'don ')", 2063 | "value": 4 2064 | }, { 2065 | "target": "('randy ', 'lenz ')", 2066 | "source": "('gately ', 'don ')", 2067 | "value": 26 2068 | }, { 2069 | "target": "('bobby c ',)", 2070 | "source": "('gately ', 'don ')", 2071 | "value": 7 2072 | }, { 2073 | "target": "('pamela hoffman-jeep ', 'hoffman-jeep ')", 2074 | "source": "('gately ', 'don ')", 2075 | "value": 8 2076 | }, { 2077 | "target": "('joelle ', 'van dyne ', 'lucille ')", 2078 | "source": "('gately ', 'don ')", 2079 | "value": 24 2080 | }, { 2081 | "target": "('wraith ',)", 2082 | "source": "('gately ', 'don ')", 2083 | "value": 20 2084 | }, { 2085 | "target": "('glenn ', 'glenn k ')", 2086 | "source": "('gately ', 'don ')", 2087 | "value": 3 2088 | }, { 2089 | "target": "('ferocious francis ', 'francis ')", 2090 | "source": "('gately ', 'don ')", 2091 | "value": 12 2092 | }, { 2093 | "target": "('whitey sorkin ', 'sorkin ')", 2094 | "source": "('gately ', 'don ')", 2095 | "value": 13 2096 | }, { 2097 | "target": "('eugene ', 'fackelmann ')", 2098 | "source": "('gately ', 'don ')", 2099 | "value": 41 2100 | }, { 2101 | "target": "('waite ',)", 2102 | "source": "('gately ', 'don ')", 2103 | "value": 5 2104 | }, { 2105 | "target": "('himself ', 'mad stork ', 'jim icandenza ', 'james incandenza ')", 2106 | "source": "('eugene ', 'fackelmann ')", 2107 | "value": 5 2108 | }, { 2109 | "target": "('bobby c ',)", 2110 | "source": "('eugene ', 'fackelmann ')", 2111 | "value": 4 2112 | }, { 2113 | "target": "('pamela hoffman-jeep ', 'hoffman-jeep ')", 2114 | "source": "('eugene ', 'fackelmann ')", 2115 | "value": 3 2116 | }, { 2117 | "target": "('whitey sorkin ', 'sorkin ')", 2118 | "source": "('eugene ', 'fackelmann ')", 2119 | "value": 10 2120 | }, { 2121 | "target": "('eighties bill ',)", 2122 | "source": "('eugene ', 'fackelmann ')", 2123 | "value": 3 2124 | }, { 2125 | "target": "('gately ', 'don ')", 2126 | "source": "('eugene ', 'fackelmann ')", 2127 | "value": 41 2128 | }, { 2129 | "target": "('todd \"postal weight\" possalthwaite ', 'possalthwaite ', 'postal weight ')", 2130 | "source": "('waite ',)", 2131 | "value": 21 2132 | }, { 2133 | "target": "('hal ',)", 2134 | "source": "('waite ',)", 2135 | "value": 3 2136 | }, { 2137 | "target": "('gately ', 'don ')", 2138 | "source": "('waite ',)", 2139 | "value": 5 2140 | }] 2141 | } 2142 | --------------------------------------------------------------------------------