Package: tabulardf
TabulaRDFTabulaRDF - Functionality for DataFrame to RDF conversions.Although TabulaRDF was primarily designed for table to RDF conversions, theTemplateConverterclass should be general enough to allow conversions to basically any target format.Just like theTemplateGraphConverterclass parses renderings into anrdflib.Graphinstance, renderings could e.g. also get parsed into anlxml.etree.Requirementspython >= 3.11UsageTabulaRDF provides two main approaches for table conversions, a template-based approach using theJinja2templating engine and a pure Python/callable-based approach.Also a CLI for template conversions is available, seeTaCLbelow.Template convertersTemplate converters are based on the genericTemplateConverterclass which allows to iterate over a dataframe and pass table data to Jinja renderings.Two different render strategies are available through therendermethod and therender_by_rowmethod respectively.With therendermethod, every template gets passed the entire table data as "table_data";
this means that iteration must be done in the template.With therender_by_rowmethod, for every row iteration the template gets passed the current row data (as "row_data") only;
so iteration is done at the Python level, not in the template.TheTemplateGraphConverterclass uses therender_by_rowmethod and parses renderings into anrdflib.Graphinstance.importpandasaspdfromjinja2importTemplatefromtabulardfimportTemplateGraphConvertertable=[{"id":"rem","full_title":"Reference corpus Middle High German"},{"id":"SweDracor","full_title":"Swedish Drama Corpus"}]dataframe=pd.DataFrame(data=table)template=Template("""@prefix crm: <http://www.cidoc-crm.org/cidoc-crm/> .@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .{% set acronym_lower = row_data['id'] | lower %}<https://{{acronym_lower}}.clscor.io/entity/appellation/1> a crm:E41_Appellation ;crm:P2_has_type <https://core.clscor.io/entity/type/appellation_type/full_title> ;rdf:value "{{row_data['full_title']}}" .""")converter=TemplateGraphConverter(dataframe=dataframe,template=template)print(converter.serialize())Output:@prefixcrm:<http://www.cidoc-crm.org/cidoc-crm/>.@prefixrdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>.<https://rem.clscor.io/entity/appellation/1>acrm:E41_Appellation;crm:P2_has_type<https://core.clscor.io/entity/type/appellation_type/full_title>;rdf:value"Reference corpus Middle High German".<https://swedracor.clscor.io/entity/appellation/1>acrm:E41_Appellation;crm:P2_has_type<https://core.clscor.io/entity/type/appellation_type/full_title>;rdf:value"Swedish Drama Corpus".This is not a simple text rendering (note that the prefix declarations are not repeated) but anrdflibserialization!TemplateGraphConverter.serializeis a proxy forrdflib.Graph.serialze, so any serialization format can be generated.Callable convertersTabulaRDF provides two main approaches for pure Python/callable based table to RDF conversions, theRowGraphConverterclass andFieldGraphConverterclass.RowGraphConvertertakes a dataframe and a Python callable which takes a dict parameter and is responsible for returning a graph instance;
for every row iteration over the dataframe this callable gets passed the row data as a dictionary; the generated subgraphs ("row graphs") are merged into a main graph.importpandasaspdfromjinja2importTemplatefromtabulardfimportRowGraphConverterfromrdflibimportGraph,URIRef,Literal,Namespacefromrdflib.namespaceimportRDFtable=[{"id":"rem","full_title":"Reference corpus Middle High German"},{"id":"SweDracor","full_title":"Swedish Drama Corpus"}]dataframe=pd.DataFrame(data=table)defrow_rule(row_data:dict)->Graph:crm=Namespace("http://www.cidoc-crm.org/cidoc-crm/")subject_uri=URIRef(f"https://{row_data['id'].lower()}.clscor.io/entity/appellation/1")triples=[(subject_uri,RDF.type,crm["E41_Appellation"]),(subject_uri,crm["P2_has_type"],URIRef("https://core.clscor.io/entity/type/appellation_type/full_title")),(subject_uri,RDF.value,Literal(row_data["full_title"]))]graph=Graph()fortripleintriples:graph.add(triple)returngraphconverter=RowGraphConverter(dataframe=dataframe,row_rule=row_rule)print(converter.serialize())FieldGraphConverteron the other hand iterates over every field for every row in a dataframe; it applies callables to every field according to a mapping of column header names and callables responsible for returning a subgraph per field ("field graphs") which are then merged into a main graph.
Callables in such are rule mapping are of arity 3, they receivesubject_field(according to theFieldGraphConverter'ssubject_columnparameter),object_field(i.e. the value of the current field) andstore(a class level dictionary for caching data).importpandasaspdfromjinja2importTemplatefromtabulardfimportFieldGraphConverterfromrdflibimportGraph,URIRef,Literal,Namespacefromrdflib.namespaceimportRDFtable=[{"id":"rem","full_title":"Reference corpus Middle High German"},{"id":"SweDracor","full_title":"Swedish Drama Corpus"}]dataframe=pd.DataFrame(data=table)defid_rule(subject_field,object_field,store)->Graph:subject_uri=URIRef(f"https://{subject_field}.clscor.io/entity/appellation/1")crm=Namespace("http://www.cidoc-crm.org/cidoc-crm/")triples=[(subject_uri,RDF.type,crm["E41_Appellation"]),(subject_uri,crm["P2_has_type"],URIRef("https://core.clscor.io/entity/type/appellation_type/full_title"))]graph=Graph()fortripleintriples:graph.add(triple)returngraphdeffull_title_rule(subject_field,object_field,store)->Graph:subject_uri=URIRef(f"https://{subject_field}.clscor.io/entity/appellation/1")graph=Graph()graph.add((subject_uri,RDF.value,Literal(object_field)))returngraphcolumn_rules={"id":id_rule,"full_title":full_title_rule}converter=FieldGraphConverter(dataframe=dataframe,subject_column="id",subject_rule=str.lower,column_rules=column_rules)print(converter.serialize())Ifsubject_ruleis supplied,subject_fieldin acolumn_rulecallable will be whatsubject_rulecomputes it to be.
As mentioned,storeis a class level attribute for sharing state between callables.Both RowgraphConverter and FieldGraphConverter produce the same output.TaCLTaCL is a humble CLI for tabulaRDF template conversions.
[todo: description + examples]