Building a Data Profiler
This command-line data profiler is a small side project I've been working on to help get a quick understanding of an unfamiliar dataset. It currently supports JSON, but I'm building the application around a pipeline that will eventually accommodate other file formats.
The current workflow is roughly: 1. Parse file into an abstract syntax tree (AST); 2. Explode the AST into a tabular format; 3. Analyze the output; 4. Output a report in html format.
For JSON, the file is parsed into an AST that preserves the structure of the objects, arrays, values, paths and their relationships in the original file.
The AST is exploded into tabular format and loaded into a DuckDB in-memory database where SQL is used to perform analytical work. The profiling logic is separate from the JSON parsing mechanics.
The analytical layer uses SQL queries with DuckDB. Once the data is transformed into a representation suitable for analysis, SQL can be used to answer questions about the file structure like field occurrence, object depth, array cardinality and structural variation.
The results of these analytical queries are passed to a Report class which actually runs these queries against DuckDB and assembles the information needed for the report. The report is then rendered as HTML using Jinja templates, which are intentionally kept as a dumb presentation layer. All business logic is encapsulated in a Report class.
A cli ties the application together and provides an interface for profiling a file without having to write a python script.
One of the more interesting problems so far has been understanding JSON arrays. A path such as $.results[*] describes the structure of an array, while an instance path such as $.results[12] identifies a specific element. Keeping these concepts separate makes it possible to analyze both the overall shape of an array and the individual objects in it. This helps the profiler answer question like:
- How many objects occur at a particular path?
- What keys are present in those objects?
- What percentage of objects contain each key?
- How many elements does an array contain?
- How homogeneous are objects within an array?
The project is still evolving, but the architecture is starting to settle on clear responsibilities: Parsers for each file format. Analysis is performed with SQL against DuckDB. A Report class assembles results. Jinja presents results. 5. A cli ties everything together.