{"id":141,"date":"2018-07-09T21:39:51","date_gmt":"2018-07-09T21:39:51","guid":{"rendered":"http:\/\/sarahjpurcell.sites.grinnell.edu\/sandbox_clone\/?page_id=141"},"modified":"2018-11-04T20:12:17","modified_gmt":"2018-11-04T20:12:17","slug":"network-analysis-ii","status":"publish","type":"page","link":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/tutorials\/network-analysis-ii\/","title":{"rendered":"Network Analysis-Part III (NetworkX)"},"content":{"rendered":"<p>This tutorial was written by <a href=\"https:\/\/www.grinnell.edu\/users\/waldenka\">Katherine Walden<\/a>, Digital Liberal Arts Specialist at Grinnell College.<\/p>\n<p>This tutorial was reviewed by <a href=\"https:\/\/www.grinnell.edu\/users\/purcelsj\">Sarah Purcell<\/a> (L.F. Parker Professor of History) and <a href=\"https:\/\/www.grinnell.edu\/users\/donovang\">Gina Donovan<\/a> (Instructional Technologist) at Grinnell College, and edited by Papa Ampim-Darko, a student research assistant at Grinnell College.<\/p>\n<p>This tutorial is adapted from the Programming Historian\u2019s <a href=\"https:\/\/programminghistorian.org\/en\/lessons\/exploring-and-analyzing-network-data-with-python\">Exploring and Analyzing Network Data with Python tutorial<\/a>.<\/p>\n<p><a href=\"http:\/\/creativecommons.org\/licenses\/by-nc\/4.0\/\" rel=\"license\"><img decoding=\"async\" style=\"border-width: 0;\" src=\"https:\/\/i.creativecommons.org\/l\/by-nc\/4.0\/88x31.png\" alt=\"Creative Commons License\" \/><\/a><br \/>\nNetwork Analysis-Part II (NetworkX) is licensed under a <a href=\"http:\/\/creativecommons.org\/licenses\/by-nc\/4.0\/\" rel=\"license\">Creative Commons Attribution-NonCommercial 4.0 International License<\/a>.<\/p>\n<hr \/>\n<p><em>GUI interfaces like Palladio and Gephi help researchers use digital tools quickly without requiring extensive technical documentation. But, larger data sets or more complex analysis often goes beyond the capacity of a GUI tool. In the next section of the tutorial, we will be using <a href=\"https:\/\/networkx.github.io\/documentation\/stable\/index.html\">NetworkX<\/a>, a Python package, to analyze and study more complex aspects of the Quaker data. NetworkX is a free Python library developed and released in 2005.<\/em><\/p>\n<hr \/>\n<h5>Getting the Data<\/h5>\n<p>We will be working with sample networked data sets based on the <a href=\"http:\/\/www.oxforddnb.com\/\">Oxford Dictionary of National Biography<\/a> and the <a href=\"http:\/\/www.sixdegreesoffrancisbacon.com\/\">Six Degrees of Francis Bacon<\/a> project. These data sets include a list of names and relationships for early seventeenth-century Quakers. Navigate to \\storageprojectsHISHIS-295-02Quaker_Network_Data and copy the quakers_nodelist and quakers_edgelist CSV files to your Desktop. Or, visit <a href=\"http:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/files\/\">http:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/files\/<\/a> and download the same files.<\/p>\n<hr \/>\n<h5>Installing NetworkX<\/h5>\n<p><a href=\"http:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_networkx.png\"><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-602\" src=\"http:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_networkx.png\" alt=\"\" width=\"740\" height=\"736\" srcset=\"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_networkx.png 740w, https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_networkx-150x150.png 150w, https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_networkx-300x298.png 300w, https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_networkx-676x672.png 676w\" sizes=\"(max-width: 740px) 100vw, 740px\" \/><\/a><\/p>\n<p>Python is already installed on the Library lab computers. To install NetworkX, navigate to C:\\Python27\\Scripts in File Explorer.<\/p>\n<p><a href=\"http:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_3-4.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-600\" src=\"http:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_3-4.png\" alt=\"\" width=\"982\" height=\"514\" srcset=\"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_3-4.png 982w, https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_3-4-300x157.png 300w, https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_3-4-768x402.png 768w, https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_3-4-676x354.png 676w\" sizes=\"(max-width: 982px) 100vw, 982px\" \/><\/a><\/p>\n<p>Type cmd in the File Explorer navigation bar, and hit the Enter key. A command prompt window will open.<\/p>\n<blockquote>\n<pre>pip install networkx<\/pre>\n<\/blockquote>\n<p>Type pip install networkx in the command prompt window and hit the Enter key to install the NetworkX Python library.<\/p>\n<p><a href=\"http:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_4-4.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-601\" src=\"http:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_4-4.png\" alt=\"\" width=\"979\" height=\"281\" srcset=\"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_4-4.png 979w, https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_4-4-300x86.png 300w, https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_4-4-768x220.png 768w, https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-content\/uploads\/2018\/08\/Capture_4-4-676x194.png 676w\" sizes=\"(max-width: 979px) 100vw, 979px\" \/><\/a><\/p>\n<blockquote>\n<pre>pip install community<\/pre>\n<\/blockquote>\n<p>Type pip install community in the command prompt window and hit the Enter key to install the Community Python library.<\/p>\n<p>Close the command prompt window after the install has completed.<\/p>\n<p>If you want to install Python or NetworkX on your own computer, consult <a href=\"https:\/\/programminghistorian.org\/en\/lessons\/exploring-and-analyzing-network-data-with-python\">The Programming Historian\u2019s tutorial<\/a> for additional instructions.<\/p>\n<hr \/>\n<h5>Loading Network Data in Python<\/h5>\n<p>1-We will be working with the same nodelist and edgelist CSV files we downloaded at the start of this tutorial. <strong>Copy or move those files into your Python directory (C:Python\u2026) using File Explorer.<\/strong><\/p>\n<p>2-Click <strong>Start-&gt;All Programs-&gt;Python-&gt;IDLE (Python)<\/strong> to open Python\u2019s GUI coding interface.<\/p>\n<p>3-Start your Python file by importing the libraries and packages we\u2019ll need to use NetworkX.<\/p>\n<blockquote>\n<pre>import csv\r\nimport networkx as nx\r\nfrom operator import itemgetter\r\nimport community<\/pre>\n<\/blockquote>\n<p>4-CSV and itemgetter are built-in Python libraries, and we installed the NetworkX and Community libraries in the first part of this tutorial.<\/p>\n<p>5-Now we\u2019ll add code that tells Python to open the nodelist and edgelist CSV files and read the data contained in those files. Feel free to re-type this code, but you can also copy and paste from the online WordPress tutorial.<\/p>\n<blockquote>\n<pre>with open('quakers_nodelist.csv', 'r') as nodecsv: <em># Open the file\u00a0\u00a0\u00a0<\/em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n\u00a0\u00a0\u00a0 nodereader = csv.reader(nodecsv) <em># Read the csv\u00a0<\/em>\r\n<em>\u00a0\u00a0\u00a0 # Retrieve the data (using Python list comprehension and list slicing to remove the header row)<\/em>\r\n\u00a0\u00a0\u00a0 nodes = [n for n in nodereader][1:]\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\nnode_names = [n[0] for n in nodes]<em> # Get a list of only the node names<\/em>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\nwith open('quakers_edgelist.csv', 'r') as edgecsv: <em># Open the file<\/em>\r\n\u00a0\u00a0\u00a0 edgereader = csv.reader(edgecsv)<em> # Read the csv\u00a0\u00a0\u00a0\u00a0<\/em>\r\n\u00a0\u00a0\u00a0 edges = [tuple(e) for e in edgereader][1:]<em> # Retrieve the data<\/em><\/pre>\n<\/blockquote>\n<p><em>\u00a06-<\/em>With open opens our CSV files in the read (\u2018r\u2019) mode and creates lists named nodecsv and edgecsv with that data. The additional indented lines read the CSV data, analyze the node names, retrieve the edge data, and remove the descriptive header information.<\/p>\n<p>7-From these commands, we have a list of node names and edge pairs which will be the foundation of our network analysis.<\/p>\n<p>8-Before moving forward, let\u2019s check to make sure our data has loaded correctly into Python.<\/p>\n<blockquote>\n<pre>print(len(node_names)) <em># prints the count of node names<\/em>\r\nprint(len(edges)) <em># prints the total count of edges<\/em><\/pre>\n<\/blockquote>\n<p>9-If you reopened the CSV files, you could confirm that Python had correctly loaded 119 node names (number of rows in the nodelist file) and 174 edges (number of rows in the edgelist file).<\/p>\n<hr \/>\n<h5>Creating a NetworkX Graph<\/h5>\n<p>10-Right now, we have a list of <strong>nodes<\/strong> (node_names) and a list of <strong>edges<\/strong> (edges) in Python. NetworkX will allow us to combine those lists in a network analysis, a <strong>Graph data object<\/strong> in NetworkX.<\/p>\n<p>11-Use G=nx.Graph() to initialize a Graph object. Right now the G graph object is empty.<\/p>\n<ul>\n<li>G.add_nodes_from(node_names) adds node names from our node_names list.<\/li>\n<li>G.add_edges_from(edges) adds edges from our edges list<\/li>\n<\/ul>\n<blockquote>\n<pre>G=nx.Graph() \r\nG.add_nodes_from(node_names) \r\nG.add_edges_from(edges)<\/pre>\n<\/blockquote>\n<p>12-Use print(nx.info(G)) to output information about our newly-created Graph object, including the number of nodes, edges, and the average degree (average number of connections for each node). Keep in mind, unlike the network graph we created in Palladio, NetworkX is creating a Graph data object, not a network visualization.<\/p>\n<blockquote>\n<pre>print(nx.info(G))<\/pre>\n<\/blockquote>\n<hr \/>\n<h5>Adding Data Attributes in NetworkX<\/h5>\n<p>13-The power of NetworkX allows you to add attributes to the nodes and edges in your Graph object. We\u2019ll add this data through a two-step process\u2014creating a Python dictionary for the attribute values, then connecting the attributes in the dictionary to the appropriate node.<\/p>\n<blockquote><p><em>Hang in there\u2014the next step is the most technically complex part of this tutorial.<\/em><\/p><\/blockquote>\n<p>14-We\u2019ll create empty dictionaries for each of the attribute fields in our nodelist CSV file.<\/p>\n<blockquote>\n<pre>hist_sig_dict = {}\r\ngender_dict = {}\r\nbirth_dict = {}\r\ndeath_dict = {}\r\nid_dict = {}<\/pre>\n<\/blockquote>\n<p>15-We\u2019ll now tell Python to go through the data in the nodes list (from the nodelist CSV) and add the appropriate items to each dictionary. Python is able to do this because our data from the CSV files is structured and has position or index information that enables Python to correctly put items in dictionaries.<\/p>\n<blockquote>\n<pre>for node in nodes: # Loop through the list, one row at a time\u00a0\u00a0\u00a0 \r\n    hist_sig_dict[node[0]] = node[1]\u00a0\u00a0\u00a0 \r\n    gender_dict[node[0]] = node[2]\u00a0\u00a0\u00a0 \r\n    birth_dict[node[0]] = node[3]\u00a0\u00a0\u00a0 \r\n    death_dict[node[0]] = node[4]\u00a0\u00a0\u00a0 \r\n    id_dict[node[0]] = node[5]<\/pre>\n<\/blockquote>\n<p>16-For node in nodes and the subsequent indented lines created a set of Python dictionaries we can now use to add those attributes to our Graph data object in NetworkX.<\/p>\n<p>17-NetworkX uses a set_nodes_attributes function to connect the Graph object and the dictionary with attribute information, and creates a name for the newly-added attribute information<\/p>\n<blockquote>\n<pre>nx.set_node_attributes(G, hist_sig_dict, 'historical_significance') \r\nnx.set_node_attributes(G, gender_dict, 'gender')\r\nnx.set_node_attributes(G, birth_dict, 'birth_year')\r\nnx.set_node_attributes(G, death_dict, 'death_year')\r\nnx.set_node_attributes(G, id_dict, 'sdfb_id')<\/pre>\n<\/blockquote>\n<p>18-G is our Graph object, hist_sig_dict (etc) is our dictionary with attribute data, and \u2018historical_significance\u2019 is the name for the new attribute data in the Graph object.<\/p>\n<p>19-Now that all of our nodes are connected to attribute data, we can print out specific combinations of nodes and attributes.<\/p>\n<blockquote>\n<pre>for n in G.nodes(): # Loop through every node, in our data \"n\" will be the name of the person\u00a0\u00a0\u00a0 \r\n    print(n, G.node[n]['birth_year']) # Access every node by name and \"birth_year\" attribute<\/pre>\n<\/blockquote>\n<hr \/>\n<h4 style=\"text-align: center;\">Calculating metrics in NetworkX<\/h4>\n<p>Given how easily we were able to load data and visualize a network in Palladio, the detailed Python coding may seem like an unnecessary burden. However, the metrics NetworkX allows us to calculate for our network data provide greater insight and detail that the visualizations we were able to generate in Palladio.<\/p>\n<hr \/>\n<h5>Structural Calculations<\/h5>\n<h5>20-Density<\/h5>\n<blockquote>\n<pre>density=nx.density(G)\r\nprint(\u201cNetwork density:\u201d, density)<\/pre>\n<\/blockquote>\n<p>Creates an object named density and uses NetworkX to calculate density for our Graph object. Print displays the output for the density calculation.<\/p>\n<p>On a scale of 0 to 1, our network is not very dense, which is consistent with the visualizations we saw in Palladio.<\/p>\n<h5>21-Shortest path<\/h5>\n<blockquote>\n<pre>fell_whitehead_path=nx.shortest_path(G, source=\u201dMargaret Fell\u201d, target=\u201dGeorge Whitehead\u201d)\r\nprint(\u201cShortest path between Fell and Whitehead:\u201d, fell_whitehead_path)<\/pre>\n<\/blockquote>\n<p>Creates an object named fell_whitehead_path and uses NetworkX to calculate the shortest path (or number of connections) between Margaret Fell and George Whitehead.<\/p>\n<p>Why would a shortest path calculation be useful? In this case, we learn the shortest path from Fell to Whitehead goes through George Fox, a connection that might not have been clear in a network visualization.<\/p>\n<h5>22-Diameter<\/h5>\n<pre>diameter=nx.diameter(G)<\/pre>\n<p>Running the diameter=nx.diameter(G) command will give us the error message that diameter cannot be calculated since our Graph is not connected.<\/p>\n<p>A connected Graph would be one in which all nodes are connected in some way. If we remember our Palladio visualization, not all of our nodes are connected.<\/p>\n<p>Instead, we can identify the most significant component or section of our network and calculate that component\u2019s diameter.<\/p>\n<blockquote>\n<pre><em># If your Graph has more than one component, this will return False\r\n<\/em>\r\nprint(nx.is_connected(G))\u00a0\r\n<em>\r\n# Next, use nx.connected_components to get the list of components,<\/em>\r\n<em># then use the max() command to find the largest one:<\/em>\r\n\r\ncomponents = nx.connected_components(G)\r\nlargest_component = max(components, key=len)\u00a0\r\n<em>\r\n# Create a \"subgraph\" of just the largest component<\/em>\r\n<em># Then calculate the diameter of the subgraph, just like you did with density.<\/em> \r\n\r\nsubgraph = G.subgraph(largest_component)\r\ndiameter = nx.diameter(subgraph)\r\nprint(\"Network diameter of largest component:\", diameter)<\/pre>\n<\/blockquote>\n<hr \/>\n<h5>Centrality Measures<\/h5>\n<h5>23-Degree<\/h5>\n<blockquote>\n<pre>degree_dict=dict(G.degree(G.nodes()))\r\nnx.set_node_attributes(G, degree_dict, \u2018degree\u2019)\r\nprint(degree_dict)<\/pre>\n<\/blockquote>\n<p>Creates an object named degree_dict and uses NetworkX to calculate the degree of centrality on the nodes in the Graph object. The second line of code adds that centrality calculation to each node as an attribute.<\/p>\n<p>But a useful way to use the degree calculation is to compare relative centrality of different nodes, which we can do using the sort and itemgetter functions.<\/p>\n<blockquote>\n<pre>sorted_degree=sorted(degree_dict.items(), key=itemgetter(1), reverse=True)\r\nprint(sorted_degree)<\/pre>\n<\/blockquote>\n<p>Don\u2019t worry too much about all\u00a0 that\u2019s going on with this code\u2014you are identifying the dictionary you want to sort (degree_dict), selecting the items from within that dictionary that you want to sort (key=itemgetter(1)), and reversing the sorted function so the highest degree of centrality nodes will appear first on the list.<\/p>\n<h5>24-Betweenness centrality<\/h5>\n<p>However, we probably didn\u2019t need a degree of centrality calculation to confirm William Penn and George Fox would be significantly central figures in our network of 17<sup>th<\/sup> century Quakers.<\/p>\n<p>Betweenness centrality calculates the number of shortest path routes that go through a specific node. These \u2018broker\u2019 nodes often may not be central in the standard network calculation, but they are incredibly significant to the network\u2019s structure.<\/p>\n<blockquote>\n<pre>betweenness_dict = nx.betweenness_centrality(G) <em># Run betweenness centrality\r\n<\/em>\r\nnx.set_node_attributes(G, betweenness_dict, 'betweenness')\r\nsorted_betweenness = sorted(betweenness_dict.items(), key=itemgetter(1), reverse=True)\r\n\u00a0\r\nprint(\"Top 20 nodes by betweenness centrality:\")\r\nfor b in sorted_betweenness[:20]:\r\n\u00a0\u00a0\u00a0 print(b)<\/pre>\n<\/blockquote>\n<p>As we see in these results, nodes with significant Betweenness Centrality calculations are not the same list that appeared for the standard Centrality Degree calculations. Women like Mary Penington and Elizabeth Leavens have increased significance as broker nodes, when their role was not visible in the standard centrality calculations.<\/p>\n<p>We are only scratching the surface of the metrics you can calculate on a network using NetworkX. For more information and examples, consult <a href=\"https:\/\/programminghistorian.org\/en\/lessons\/exploring-and-analyzing-network-data-with-python\">The Programming Historian\u2019s tutorial<\/a>.<\/p>\n<hr \/>\n<h5>Exporting data from NetworkX<\/h5>\n<p>25-NetworkX allows us to calculate a wide range of metrics within Python, but we might want to export the network data so we can visualize it outside the Python environment.<\/p>\n<blockquote>\n<pre>nx.write_gexf(G, \u2018quaker_network.gexf\u2019)<\/pre>\n<\/blockquote>\n<p>This command exports the NetworkX Graph data object as a Gephi file, which can be opened in the Gephi network visualization software.<\/p>\n<p>If you navigate to your <strong>C:Python\u2026 directory<\/strong> in <strong>File Explorer<\/strong>, you will see a <strong>quaker_network GEXF<\/strong> Graph File.<\/p>\n<hr \/>\n<p>&nbsp;<\/p>\n<hr \/>\n<h5><em>Reflection questions<\/em><\/h5>\n<ul>\n<li><em>This was a more technically-oriented tutorial than most others in the course. What did you enjoy? What did you find challenging?<\/em><\/li>\n<li><em>What was the most confusing or unclear part of the tutorial? What questions do you have about network analysis and the digital tools historians can use to analyze networks?<\/em><\/li>\n<li><em>What was the most surprising or interesting part of the tutorial?<\/em><\/li>\n<li><em>How did you understanding of the data set change over the course of the tutorial\u2014what thoughts or questions did you have about the data when we were working with Palladio, versus NetworkX, versus Gephi?<\/em><\/li>\n<li><em>What types of historical data might be well-suited for network analysis? What kinds of data might not work well for network analysis?<\/em><\/li>\n<li><em>How would you move forward with a network analysis project? What types of data would you be interested in exploring, and what kinds of research questions would you want to ask?<\/em><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial was written by Katherine Walden, Digital Liberal Arts Specialist at Grinnell College. This tutorial was reviewed by Sarah Purcell (L.F. Parker Professor of History) and Gina Donovan (Instructional Technologist) at Grinnell College, and edited by Papa Ampim-Darko, a student research assistant at Grinnell College. This tutorial is adapted from the Programming Historian\u2019s Exploring [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":53,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-141","page","type-page","status-publish","hentry","post-preview"],"_links":{"self":[{"href":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-json\/wp\/v2\/pages\/141","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-json\/wp\/v2\/comments?post=141"}],"version-history":[{"count":21,"href":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-json\/wp\/v2\/pages\/141\/revisions"}],"predecessor-version":[{"id":700,"href":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-json\/wp\/v2\/pages\/141\/revisions\/700"}],"up":[{"embeddable":true,"href":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-json\/wp\/v2\/pages\/53"}],"wp:attachment":[{"href":"https:\/\/sarahjpurcell.sites.grinnell.edu\/digital_methods\/wp-json\/wp\/v2\/media?parent=141"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}