Perfect Hash Family Non-Distinct t Columns Calculator
For a start, use iterators. Don't convert to lists constantly:

get_column can be simplified to (use generator rather than list):

def get_column(phf, c):
    return (x[c] for x in phf)


combine_columns_into_array to:

def combine_columns_into_array(phf, cs):
    return zip(*[get_column(phf, c) for c in cs])


In count_non_distinct_combinations:

for c in combinations(range(k), t):


Rather than:

for c in combinations([i for i in range(k)], t):


To further simplify, combine_columns_into_array can be merged with get_column:

def combine_columns_into_array(phf, cs):
    return zip(*[[x[c] for x in phf] for c in cs])


Combining combine_columns_into_array into count_non_distinct_combinations:

def count_non_distinct_combinations(phf, t):
    k = len(phf[0])
    true_count = 0
    # get all combinations
    for c in combinations(range(k), t):
        b = False
        for row in zip(*[[x[i] for x in phf] for i in c]):
            # if the row is completely distinct
            if len(row) == len(set(row)):
                b = True
        # if all rows are non-distinct:
        if not b:
            true_count += 1
    return true_count


The zip(*[[x[i] for x in phf] for i in c]) can be simplified to ([x[i] for i in c] for x in phf)

The whole

k = len(phf[0])
true_count = 0
# get all combinations
for c in combinations([i for i in range(k)], t):
    b = False
    choices = combine_columns_into_array(phf, list(c))
    for row in choices:
        # if the row is completely distinct
        if len(row) == len(set(row)):
            b = True
    # if all rows are non-distinct:
    if not b:
        true_count += 1
return true_count


section can be simplified (I think) to:

true_count = 0
# get all combinations
for c in combinations(range(len(phf[0])), t):
    s = [[x[i] for i in c] for x in phf]
    # if all rows are non-distinct:
    if not [len(i) for i in s] == [len(set(i)) for i in s]:
        true_count += 1
return true_count


And so to:

def count_non_distinct_combinations(phf, t):
    true_count = 0
    for c in combinations(range(len(phf[0])), t):
        if not any(len(set(i)) == len(i) for i in ([x[i] for i in c] for x in phf)):
            true_count += 1
    return true_count


I admit I lost readability somewhere along the line, but this new 6 line version takes 55.3% of the time needed to complete the phf2 case, so its almost twice as fast as your version. There may be improvements that can be done to the algorithm, but I'll stop here.