Returns how typical the row is (opposite of how anomalous).

def row_structural_typicality(X_L_list, X_D_list, row_id):
    """Returns how typical the row is (opposite of how anomalous)."""
    count = 0
    assert len(X_L_list) == len(X_D_list)
    for X_L, X_D in zip(X_L_list, X_D_list):
        for r in range(len(X_D[0])):
            for c in range(
                    len(X_L['column_partition']['assignments'])):
                if X_D[X_L['column_partition']['assignments'][c]][r] == \
                        X_D[X_L['column_partition']['assignments'][c]][row_id]:
                    count += 1
    return float(count) / \
        (len(X_D_list) * len(X_D[0]) *
            len(X_L_list[0]['column_partition']['assignments']))