Bringing your own problem · step 6 of 6
What you have not done yet
The number came back downgraded. Why, and what fixes it?
assume_identified=True is the flag that got a number out, and the status says exactly what it cost: downgraded. Nothing above argued that leaflet spend is unconfounded with footfall. Stores that were already busy may well have been given more leaflets.
This is the honest end of a porting exercise, not a failure of one. You now have a model of your own data that produces a decision's number with its provenance attached — and a precise statement of the one thing standing between it and a causal claim. That is where the first tutorial starts.
from axiom.identify import CausalGraph, identify
# Write down what you actually believe about how the spend was set.
world = CausalGraph.from_edges(
"busyness -> leaflets, busyness -> footfall, leaflets -> footfall",
unmeasured=["busyness"],
name="how_the_spend_was_really_set",
)
verdict = identify(world, "leaflets", "footfall")
print(f"the graph says : {verdict.status}")
print(f"it would need : {sorted(verdict.unmeasured_required)}, "
f"which nobody recorded")
print()
print("so the `downgraded` in step 5 was not a formality. What you have")
print("is a description of 24 stores, not the effect of leaflets on")
print("footfall -- and the difference is the whole subject of axiom.")
print()
print("two honest ways forward, and no third:")
print(" measure it -- record what drove the spend, and adjust")
print(" randomize it -- assign the leaflets, and the arrow disappears")
print()
print("both are the subject of the other two tutorials.")
the graph says : downgraded it would need : ['busyness'], which nobody recorded so the `downgraded` in step 5 was not a formality. What you have is a description of 24 stores, not the effect of leaflets on footfall -- and the difference is the whole subject of axiom. two honest ways forward, and no third: measure it -- record what drove the spend, and adjust randomize it -- assign the leaflets, and the arrow disappears both are the subject of the other two tutorials.
Every line above was captured by running this code at build time. The steps share one namespace, so the code on this page is the code you would type after the steps before it.