Before a table goes anywhere near a model, it is worth asking one question: how dirty is it? Three numbers from the cleaning lessons answer it, and a team can track them every night as new rows arrive.
Task: write quality_report(columns, rows, rules).
columns is the list of column names.rows is the table: a list of rows, where each row is a list with one value per column, in the same order as columns.rules maps some of the column names to a validity rule. Columns with no rule are never checked. A rule takes one of two forms:
{"min": low, "max": high}: the value must be a number (an int or a float, so text such as "42" fails) with low <= value <= high.{"allowed": [...]}: the value must be exactly one of the listed values, so "Gold" does not match "gold".A cell is missing if it is None, or a string containing nothing but whitespace (such as "" or " ").
Return a tuple of three rates, each rounded to 4 decimal places:
1.0.Measure all three on the table exactly as given, duplicates included. The table always has at least one row.