def row_structural_typicality(X_L_list, X_D_list, row_id):
    """
    Returns how typical the row is (opposite of how anomalous the row is).
    """
    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']))
