Add q226: detect circular ownership structures (#8) - #20
Open
chrisdebian wants to merge 1 commit into
Open
Conversation
Answers issue openownership#8 by building a directed graph of entity-to-entity ownership links (interestedParty -> subject, restricted to rows where both ends are entities, since only entities can be owned) and running networkx's simple_cycles to find any closed ownership loops (e.g. A owns B, B owns A), which are banned under UK law.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #8.
Adds
q226(ownershipOrControlStatement)toqbods.py, following the existingqNNNfunction style (same pattern as #19 / q225).It builds a directed graph of entity-to-entity ownership links (interestedParty → subject, restricted to rows where both ends are entities, since only an entity can be owned) and runs
networkx.simple_cyclesto find any closed ownership loops — e.g. A owns B, B owns A — which is banned under UK law per the Global Witness report linked in the issue.Returns a list of two values: a dataframe with one row per circular ownership chain found (entities involved + chain length), and a summary dict with the total number of cycles and the number of distinct entities involved in at least one cycle.
Testing: verified against synthetic data — a 3-entity cycle (A→B→C→A) is correctly detected, a non-cyclic chain (X→Y) is correctly excluded, and person-owned rows are excluded from the graph entirely. As with #19, I don't have access to the real UK PSC BODS dataset locally (the
csv/folder is gitignored), so this hasn't been validated against real data — happy to adjust if real data surfaces an edge case.