Initial Commit
Browse files- app.py +26 -0
- config.json +251 -0
- data.py +68 -0
- network.py +61 -0
- requirements.txt +7 -0
app.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import numpy as np
|
| 3 |
+
|
| 4 |
+
import gradio as gr
|
| 5 |
+
import pygwalker as pyg
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
from pygwalker.api.gradio import PYGWALKER_ROUTE, get_html_on_gradio
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
from data import df
|
| 12 |
+
from network import analysis
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
with gr.Blocks() as demo:
|
| 16 |
+
# with gr.Tab("π About"):
|
| 17 |
+
# # gr.Markdown(ABOUT_TEXT)
|
| 18 |
+
with gr.Tab("π Dashboard"):
|
| 19 |
+
gr.Label("Visually explore witches family data")
|
| 20 |
+
gr.Markdown("You can use drag-and-drop operations to explore the data, start your analysis now!")
|
| 21 |
+
pyg_app = get_html_on_gradio(df, spec="./config.json")
|
| 22 |
+
gr.HTML(pyg_app)
|
| 23 |
+
with gr.Tab("πͺ Family Connection"):
|
| 24 |
+
gr.HTML(analysis)
|
| 25 |
+
|
| 26 |
+
demo.launch(app_kwargs={"routes": [PYGWALKER_ROUTE]}).queue()
|
config.json
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"config": {
|
| 4 |
+
"defaultAggregated": true,
|
| 5 |
+
"geoms": [
|
| 6 |
+
"poi"
|
| 7 |
+
],
|
| 8 |
+
"coordSystem": "geographic",
|
| 9 |
+
"limit": -1
|
| 10 |
+
},
|
| 11 |
+
"encodings": {
|
| 12 |
+
"dimensions": [
|
| 13 |
+
{
|
| 14 |
+
"dragId": "gw_0oFN",
|
| 15 |
+
"fid": "GW_153M2HTVSG",
|
| 16 |
+
"name": "item",
|
| 17 |
+
"basename": "item",
|
| 18 |
+
"semanticType": "nominal",
|
| 19 |
+
"analyticType": "dimension"
|
| 20 |
+
},
|
| 21 |
+
{
|
| 22 |
+
"dragId": "gw_TfYx",
|
| 23 |
+
"fid": "GW_2X73E2RH6IPJOOK4G8G",
|
| 24 |
+
"name": "accusedurl",
|
| 25 |
+
"basename": "accusedurl",
|
| 26 |
+
"semanticType": "nominal",
|
| 27 |
+
"analyticType": "dimension"
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
"dragId": "gw_MK3G",
|
| 31 |
+
"fid": "GW_G0O5DCTUJ01U6ZK8G",
|
| 32 |
+
"name": "itemLabel",
|
| 33 |
+
"basename": "itemLabel",
|
| 34 |
+
"semanticType": "nominal",
|
| 35 |
+
"analyticType": "dimension"
|
| 36 |
+
},
|
| 37 |
+
{
|
| 38 |
+
"dragId": "gw_4Ud1",
|
| 39 |
+
"fid": "GW_6RT7I4HK7073D9RPOESM5CH80",
|
| 40 |
+
"name": "residence",
|
| 41 |
+
"basename": "residence",
|
| 42 |
+
"semanticType": "nominal",
|
| 43 |
+
"analyticType": "dimension"
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"dragId": "gw_fW-1",
|
| 47 |
+
"fid": "GW_M27TBC9KBOWJRWX5WS34",
|
| 48 |
+
"name": "gender",
|
| 49 |
+
"basename": "gender",
|
| 50 |
+
"semanticType": "nominal",
|
| 51 |
+
"analyticType": "dimension"
|
| 52 |
+
},
|
| 53 |
+
{
|
| 54 |
+
"dragId": "gw_YRLn",
|
| 55 |
+
"fid": "GW_2ZE8EA85LWGIU48N1GW",
|
| 56 |
+
"name": "class",
|
| 57 |
+
"basename": "class",
|
| 58 |
+
"semanticType": "nominal",
|
| 59 |
+
"analyticType": "dimension"
|
| 60 |
+
},
|
| 61 |
+
{
|
| 62 |
+
"dragId": "gw_WKTM",
|
| 63 |
+
"fid": "GW_5498MX0A38QWHP82WQA4T7971KAQCP16WRJZZU8",
|
| 64 |
+
"name": "place_of_detention",
|
| 65 |
+
"basename": "place_of_detention",
|
| 66 |
+
"semanticType": "nominal",
|
| 67 |
+
"analyticType": "dimension"
|
| 68 |
+
},
|
| 69 |
+
{
|
| 70 |
+
"dragId": "gw_u9Xa",
|
| 71 |
+
"fid": "GW_R8BM6NZ296ISPYXOCTXCNQEAVA6142MCW7RHG7RLLBK26Z9POPYCZ4",
|
| 72 |
+
"name": "manner_of_inhumane_treatment",
|
| 73 |
+
"basename": "manner_of_inhumane_treatment",
|
| 74 |
+
"semanticType": "nominal",
|
| 75 |
+
"analyticType": "dimension"
|
| 76 |
+
},
|
| 77 |
+
{
|
| 78 |
+
"dragId": "gw_DUxe",
|
| 79 |
+
"fid": "GW_2AJUGNLE6MEPTZNHZAYG8IEPPSCE4MO1C",
|
| 80 |
+
"name": "cause_of_death",
|
| 81 |
+
"basename": "cause_of_death",
|
| 82 |
+
"semanticType": "nominal",
|
| 83 |
+
"analyticType": "dimension"
|
| 84 |
+
},
|
| 85 |
+
{
|
| 86 |
+
"dragId": "gw_wtxd",
|
| 87 |
+
"fid": "GW_1AW6HAPIZKT3VHC18C33DQM3968",
|
| 88 |
+
"name": "occupation",
|
| 89 |
+
"basename": "occupation",
|
| 90 |
+
"semanticType": "nominal",
|
| 91 |
+
"analyticType": "dimension"
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"dragId": "gw_EEfP",
|
| 95 |
+
"fid": "GW_OMQ0RHNFV2PIFPFR6A0G",
|
| 96 |
+
"name": "spouse",
|
| 97 |
+
"basename": "spouse",
|
| 98 |
+
"semanticType": "nominal",
|
| 99 |
+
"analyticType": "dimension"
|
| 100 |
+
},
|
| 101 |
+
{
|
| 102 |
+
"dragId": "gw_AtER",
|
| 103 |
+
"fid": "GW_GGYX5I6DWC5400P4G",
|
| 104 |
+
"name": "longitude",
|
| 105 |
+
"basename": "longitude",
|
| 106 |
+
"semanticType": "quantitative",
|
| 107 |
+
"analyticType": "dimension"
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"dragId": "gw_q-LU",
|
| 111 |
+
"fid": "GW_2BCEDJ2KYSIN2ZHS",
|
| 112 |
+
"name": "latitude",
|
| 113 |
+
"basename": "latitude",
|
| 114 |
+
"semanticType": "quantitative",
|
| 115 |
+
"analyticType": "dimension"
|
| 116 |
+
},
|
| 117 |
+
{
|
| 118 |
+
"fid": "GW_1K1RWLJMRKVG0",
|
| 119 |
+
"name": "father",
|
| 120 |
+
"semanticType": "nominal",
|
| 121 |
+
"analyticType": "dimension",
|
| 122 |
+
"basename": "father",
|
| 123 |
+
"dragId": "GW_BFrlUJKd"
|
| 124 |
+
},
|
| 125 |
+
{
|
| 126 |
+
"fid": "GW_CHAWSEHZCMSO4W",
|
| 127 |
+
"name": "sibling",
|
| 128 |
+
"semanticType": "nominal",
|
| 129 |
+
"analyticType": "dimension",
|
| 130 |
+
"basename": "sibling",
|
| 131 |
+
"dragId": "GW_enUhIyMF"
|
| 132 |
+
},
|
| 133 |
+
{
|
| 134 |
+
"fid": "GW_7NIDHER5RU8",
|
| 135 |
+
"name": "child",
|
| 136 |
+
"semanticType": "nominal",
|
| 137 |
+
"analyticType": "dimension",
|
| 138 |
+
"basename": "child",
|
| 139 |
+
"dragId": "GW_c7Noxzdq"
|
| 140 |
+
},
|
| 141 |
+
{
|
| 142 |
+
"fid": "GW_1NWT9FT2YJVAO",
|
| 143 |
+
"name": "mother",
|
| 144 |
+
"semanticType": "nominal",
|
| 145 |
+
"analyticType": "dimension",
|
| 146 |
+
"basename": "mother",
|
| 147 |
+
"dragId": "GW_YApxzLXH"
|
| 148 |
+
}
|
| 149 |
+
],
|
| 150 |
+
"measures": [
|
| 151 |
+
{
|
| 152 |
+
"dragId": "gw_count_fid",
|
| 153 |
+
"fid": "gw_count_fid",
|
| 154 |
+
"name": "Row count",
|
| 155 |
+
"analyticType": "measure",
|
| 156 |
+
"semanticType": "quantitative",
|
| 157 |
+
"aggName": "sum",
|
| 158 |
+
"computed": true,
|
| 159 |
+
"expression": {
|
| 160 |
+
"op": "one",
|
| 161 |
+
"params": [],
|
| 162 |
+
"as": "gw_count_fid"
|
| 163 |
+
}
|
| 164 |
+
},
|
| 165 |
+
{
|
| 166 |
+
"dragId": "gw_mea_val_fid",
|
| 167 |
+
"fid": "GW_4KYB9KVI3CK37NQAUJ65UJWVK",
|
| 168 |
+
"name": "Measure values",
|
| 169 |
+
"analyticType": "measure",
|
| 170 |
+
"semanticType": "quantitative",
|
| 171 |
+
"aggName": "sum"
|
| 172 |
+
}
|
| 173 |
+
],
|
| 174 |
+
"rows": [],
|
| 175 |
+
"columns": [],
|
| 176 |
+
"color": [
|
| 177 |
+
{
|
| 178 |
+
"dragId": "gw_I8g7",
|
| 179 |
+
"fid": "GW_2ZE8EA85LWGIU48N1GW",
|
| 180 |
+
"name": "class",
|
| 181 |
+
"basename": "class",
|
| 182 |
+
"semanticType": "nominal",
|
| 183 |
+
"analyticType": "dimension"
|
| 184 |
+
}
|
| 185 |
+
],
|
| 186 |
+
"opacity": [],
|
| 187 |
+
"size": [],
|
| 188 |
+
"shape": [],
|
| 189 |
+
"radius": [],
|
| 190 |
+
"theta": [],
|
| 191 |
+
"longitude": [
|
| 192 |
+
{
|
| 193 |
+
"dragId": "gw_y2hj",
|
| 194 |
+
"fid": "GW_GGYX5I6DWC5400P4G",
|
| 195 |
+
"name": "longitude",
|
| 196 |
+
"basename": "longitude",
|
| 197 |
+
"semanticType": "quantitative",
|
| 198 |
+
"analyticType": "dimension"
|
| 199 |
+
}
|
| 200 |
+
],
|
| 201 |
+
"latitude": [
|
| 202 |
+
{
|
| 203 |
+
"dragId": "gw_vshP",
|
| 204 |
+
"fid": "GW_2BCEDJ2KYSIN2ZHS",
|
| 205 |
+
"name": "latitude",
|
| 206 |
+
"basename": "latitude",
|
| 207 |
+
"semanticType": "quantitative",
|
| 208 |
+
"analyticType": "dimension"
|
| 209 |
+
}
|
| 210 |
+
],
|
| 211 |
+
"geoId": [],
|
| 212 |
+
"details": [
|
| 213 |
+
{
|
| 214 |
+
"dragId": "gw_KQnh",
|
| 215 |
+
"fid": "GW_6RT7I4HK7073D9RPOESM5CH80",
|
| 216 |
+
"name": "residence",
|
| 217 |
+
"basename": "residence",
|
| 218 |
+
"semanticType": "nominal",
|
| 219 |
+
"analyticType": "dimension"
|
| 220 |
+
}
|
| 221 |
+
],
|
| 222 |
+
"filters": [],
|
| 223 |
+
"text": []
|
| 224 |
+
},
|
| 225 |
+
"layout": {
|
| 226 |
+
"showActions": false,
|
| 227 |
+
"showTableSummary": false,
|
| 228 |
+
"stack": "stack",
|
| 229 |
+
"interactiveScale": false,
|
| 230 |
+
"zeroScale": true,
|
| 231 |
+
"size": {
|
| 232 |
+
"mode": "auto",
|
| 233 |
+
"width": 800,
|
| 234 |
+
"height": 800
|
| 235 |
+
},
|
| 236 |
+
"format": {},
|
| 237 |
+
"geoKey": "name",
|
| 238 |
+
"resolve": {
|
| 239 |
+
"x": false,
|
| 240 |
+
"y": false,
|
| 241 |
+
"color": false,
|
| 242 |
+
"opacity": false,
|
| 243 |
+
"shape": false,
|
| 244 |
+
"size": false
|
| 245 |
+
},
|
| 246 |
+
"scaleIncludeUnmatchedChoropleth": false
|
| 247 |
+
},
|
| 248 |
+
"visId": "gw_b4Sl",
|
| 249 |
+
"name": "Chart 1"
|
| 250 |
+
}
|
| 251 |
+
]
|
data.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
from SPARQLWrapper import SPARQLWrapper, JSON
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
endpoint_url = "https://query.wikidata.org/sparql"
|
| 8 |
+
|
| 9 |
+
query = """
|
| 10 |
+
# Places of residence of accused witches in Scotland 1563-1736
|
| 11 |
+
SELECT ?accusedurl ?item ?itemLabel ?residenceLabel ?genderLabel ?occupationLabel ?classLabel ?manner_of_inhumane_treatmentLabel ?place_of_detentionLabel ?cause_of_deathLabel ?fatherLabel ?motherLabel ?siblingLabel ?childLabel ?spouseLabel ?coords WHERE {
|
| 12 |
+
?item wdt:P31 wd:Q5;
|
| 13 |
+
wdt:P4478 ?accused.
|
| 14 |
+
wd:P4478 wdt:P1630 ?formatterurl.
|
| 15 |
+
BIND(IRI(REPLACE(?accused, "^(.+)$", ?formatterurl)) AS ?accusedurl)
|
| 16 |
+
?item wdt:P551 ?residence.
|
| 17 |
+
?residence wdt:P625 ?coords.
|
| 18 |
+
|
| 19 |
+
OPTIONAL { ?item wdt:P21 ?gender. }
|
| 20 |
+
OPTIONAL { ?item wdt:P106 ?occupation. }
|
| 21 |
+
OPTIONAL { ?item wdt:P3716 ?class. }
|
| 22 |
+
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
|
| 23 |
+
OPTIONAL { ?item wdt:P7160 ?manner_of_inhumane_treatment. }
|
| 24 |
+
OPTIONAL { ?item wdt:P2632 ?place_of_detention. }
|
| 25 |
+
OPTIONAL { ?item wdt:P509 ?cause_of_death. }
|
| 26 |
+
OPTIONAL { ?item wdt:P22 ?father. }
|
| 27 |
+
OPTIONAL { ?item wdt:P25 ?mother. }
|
| 28 |
+
OPTIONAL { ?item wdt:P3373 ?sibling. }
|
| 29 |
+
OPTIONAL { ?item wdt:P40 ?child. }
|
| 30 |
+
OPTIONAL { ?item wdt:P26 ?spouse. }
|
| 31 |
+
OPTIONAL { ?item wdt:P551 ?residence. }
|
| 32 |
+
}
|
| 33 |
+
"""
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def get_results(endpoint_url, query):
|
| 37 |
+
"""
|
| 38 |
+
Obtain SPARQL query results.
|
| 39 |
+
"""
|
| 40 |
+
user_agent = "WDQS-example Python/%s.%s" % (sys.version_info[0], sys.version_info[1])
|
| 41 |
+
# TODO adjust user agent; see https://w.wiki/CX6
|
| 42 |
+
sparql = SPARQLWrapper(endpoint_url, agent=user_agent)
|
| 43 |
+
sparql.setQuery(query)
|
| 44 |
+
sparql.setReturnFormat(JSON)
|
| 45 |
+
return sparql.query().convert()
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def load_data():
|
| 49 |
+
"""
|
| 50 |
+
Obtain data for accused witches charged with witchcraft.
|
| 51 |
+
"""
|
| 52 |
+
lst = []
|
| 53 |
+
results = get_results(endpoint_url, query)
|
| 54 |
+
for result in results["results"]["bindings"]:
|
| 55 |
+
d = {}
|
| 56 |
+
for k, v in result.items():
|
| 57 |
+
d[k] = v['value']
|
| 58 |
+
lst.append(d)
|
| 59 |
+
data = pd.DataFrame(lst)
|
| 60 |
+
data.dropna(subset=['siblingLabel', 'spouseLabel', 'childLabel', 'fatherLabel', 'motherLabel'], how="all", inplace=True)
|
| 61 |
+
data['longitude'] = data['coords'].str.replace("Point", "").apply(lambda x: x.split()[0].lstrip("(")).astype(float)
|
| 62 |
+
data['latitude'] = data['coords'].str.replace("Point", "").apply(lambda x: x.split()[-1].rstrip(")")).astype(float)
|
| 63 |
+
data.drop(['coords'], axis=1, inplace=True)
|
| 64 |
+
data.columns = [col.replace("Label", "") if col != "itemLabel" else col for col in data.columns.tolist()]
|
| 65 |
+
return data
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
df = load_data()
|
network.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import networkx as nx
|
| 3 |
+
import matplotlib.pyplot as plt
|
| 4 |
+
from pyvis.network import Network
|
| 5 |
+
|
| 6 |
+
from data import df
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def analysis():
|
| 10 |
+
G = nx.DiGraph()
|
| 11 |
+
|
| 12 |
+
# Define the columns to consider for relationships
|
| 13 |
+
relationship_columns = ['father', 'sibling', 'spouse', 'mother', 'child']
|
| 14 |
+
|
| 15 |
+
G.add_nodes_from(df["itemLabel"])
|
| 16 |
+
|
| 17 |
+
for index, row in df.iterrows():
|
| 18 |
+
main_entity = row['itemLabel']
|
| 19 |
+
for relationship in relationship_columns:
|
| 20 |
+
if pd.notna(row[relationship]):
|
| 21 |
+
G.add_edge(main_entity, row[relationship], relationship=str(relationship), label=relationship)
|
| 22 |
+
|
| 23 |
+
plt.figure(figsize=(50, 20)) # Set the size of the plot
|
| 24 |
+
# pos = nx.kamada_kawai_layout(G) # Compute the positions of the nodes
|
| 25 |
+
|
| 26 |
+
# # Draw the nodes and edges with labels
|
| 27 |
+
# nx.draw(G, pos, with_labels=True, node_size=20, node_color='skyblue', font_size=10, font_color='black', font_weight='bold', alpha=0.7)
|
| 28 |
+
|
| 29 |
+
# # Draw edge labels (the relationships)
|
| 30 |
+
# edge_labels = nx.get_edge_attributes(G, 'relationship')
|
| 31 |
+
# nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_color='red')
|
| 32 |
+
|
| 33 |
+
# plt.title('Relationship Graph with Labels')
|
| 34 |
+
# plt.axis('off') # Hide the axes for clarity
|
| 35 |
+
# plt.show()
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
net = Network(bgcolor="#222222", font_color="white", directed=True)
|
| 39 |
+
net.from_nx(G)
|
| 40 |
+
|
| 41 |
+
for node in net.nodes:
|
| 42 |
+
node["title"] = node["id"]
|
| 43 |
+
node["value"] = len(G[node["id"]])
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
for edge in net.edges:
|
| 47 |
+
# Set edge title to the relationship from your graph
|
| 48 |
+
relationship = G[edge["from"]][edge["to"]].get("relationship", "Unknown")
|
| 49 |
+
edge["title"] = relationship # This will show as a tooltip
|
| 50 |
+
edge["color"] = "blue"
|
| 51 |
+
edge["width"] = 2 if relationship != "Unknown" else 1
|
| 52 |
+
|
| 53 |
+
html = net.generate_html()
|
| 54 |
+
#need to remove ' from HTML
|
| 55 |
+
html = html.replace("'", "\"")
|
| 56 |
+
|
| 57 |
+
return f"""<iframe style="width: 100%; height: 1000px;margin:0 auto" name="result" allow="midi; geolocation; microphone; camera;
|
| 58 |
+
display-capture; encrypted-media;" sandbox="allow-modals allow-forms
|
| 59 |
+
allow-scripts allow-same-origin allow-popups
|
| 60 |
+
allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
|
| 61 |
+
allowpaymentrequest="" frameborder="0" srcdoc='{html}'></iframe>"""
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pandas
|
| 2 |
+
sparqlwrapper
|
| 3 |
+
gradio
|
| 4 |
+
pygwalker
|
| 5 |
+
datasets
|
| 6 |
+
pyvis
|
| 7 |
+
networkx
|