1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- # %%
- import csv
- import json
- import openpyxl as op
- # BASIC CONFIGURATION
- DATA_FOLDER = './data/'
- OUTPUT_FOLDER = './output/'
- ONTO_FILENAME = 'manoscritti_dariah' # No extension!
- ent_filename = ONTO_FILENAME + '_entities.csv'
- rel_filename = ONTO_FILENAME + '_relations.csv'
- # PART I: parse xlsx to (multiple) csv
- # Excel configuration
- XLSX_FILENAME = 'Struttura_NEW.xlsx'
- ENTITIES_SHEETNAME = 'Entità'
- RELATIONS_SHEETNAME = 'Relazioni'
- # %%
- # Import the defining xlsx through openpyxl
- input_data = op.load_workbook(DATA_FOLDER + XLSX_FILENAME)
- # Read relevant sheets
- entities_sheet = input_data[ENTITIES_SHEETNAME]
- relations_sheet = input_data[RELATIONS_SHEETNAME]
- # Parse sheet data into a dict (assuming the xlsx has headers)
- entities_keys = [cell for cell in next(entities_sheet.values) if cell]
- raw_entities = [{key: row[ind] for ind, key in enumerate(entities_keys)} for row in entities_sheet.values][1:]
- #
- relations_keys = [cell for cell in next(relations_sheet.values) if cell]
- raw_relations = [{key: row[ind] for ind, key in enumerate(relations_keys)} for row in relations_sheet.values][1:]
- # %%
- # NOTE:
- # a. Non ci sono, al momento, constraint di unicità imposti tramite il "foglio master"
- # b. Non ci sono neanche constraint di esistenza, TRANNE l'id univoca, intesa NON come quella del sistema ma quella della comunità di riferimento, e tipica del settore di dominio considerato
- # c. Per identificare le informazioni 'atomiche' non si usa un campo dedicato, ma una logica. AL MOMENTO la logica è che si considera atomica una entità che non è mai 'prima' in una relazione. L'ORDINE DELLE RELAZIONI E' IMPORTANTE a differenza di quanto assumevo inizialmente.
- # d. Si effettua un controllo di unicità sulle entità, basato sul nome normalizzato (parole con iniziale maiuscola e il resto minuscolo, spazi ridotti a spazio singolo, strip()). Nessuna entità può avere nome vuoto.
- # e. Si effettua un controllo di unicità sulle relazioni, che però riguarda tutta la terna SOGGETTO-RELAZIONE-OGGETTO (normalizzata in modo simile ai nomi di entità, ma nella RELAZIONE gli spazi sono underscores e si usa lower() invece che title()). Nessuno dei membri della terna può essere vuoto, il nome della relazione inversa è opzionale.
- # f. Si effettuano controlli di consistenza sulle relazioni:
- # .f1. Nessuna relazione con entità non definite
- # .f2. Nessuna entità "orfana", ovvero non presente in alcuna relazione
- #
- # TODO: completare secondo le specifiche sopra
- # TODO: effettuare il merge con i "miei" CSV, che hanno informazioni in più!
- # Process entities:
- # 1. Filter out unnamed entities, find out aliases, normalize entity names, find out duplicates
- clean_entities = {}
- for ent in raw_entities:
- entity_names = ent['Concetto']
- if not isinstance(entity_names, str):
- continue
- aliases = [al.strip().title() for al in entity_names.split('\n') if al.strip()]
- if not aliases:
- continue
- entity_name = aliases[0]
- entity_same_as = aliases[1:]
- if clean_entities.get(entity_name):
- # DUPLICATE!
- clean_entities[entity_name].append({'Alias': aliases, 'Raw': ent})
- else:
- clean_entities[entity_name] = [{'Alias': aliases, 'Raw': ent}]
- all_entities = clean_entities.keys()
- duplicated_entities = [ent_name for ent_name, ent_val in clean_entities.items() if len(ent_val)>1]
- # %%
- # Process relations:
- # 1. Filter ill-formed relations and normalize entity names
- clean_relations = []
- for rel in raw_relations:
- subj = rel['Soggetto']
- obj = rel['Oggetto']
- if not isinstance(subj, str) or not isinstance(obj, str):
- continue
- subj = subj.strip().title()
- obj = obj.strip().title()
- if subj==obj:
- continue
- rel_name = rel['Relazione']
- if isinstance(rel_name, str):
- rel_name = rel_name.strip().lower()
- better_rel = {'Soggetto': subj, 'Relazione': rel_name, 'Oggetto': obj, 'Pair': tuple(set([subj, obj]))}
- clean_relations.append(better_rel)
- all_pairs = [rel['Pair'] for rel in clean_relations]
- all_cited_entities = set(sum([[rel['Soggetto'], rel['Oggetto']] for rel in clean_relations], []))
- undefined_entities = all_cited_entities - all_entities
- # %%
|