import math


def dunning_log_likelihood(f1, s1, f2, s2):
    """Calculates Dunning log likelihood of an observation in two groups.

    This determines if an observation is more strongly associated with
    one of two groups, and the strength of that association.

    Args:
        f1: Integer, observation frequency in group one.
        s1: Integer, total data points in group one.
        f2: Integer, observation frequency in group two.
        s2: Integer, total data points in group two.

    Returns:
        Float log likelihood. This will be positive if the
        observation is more likely in group one. More extreme
        values indicate a stronger association.
    """
    if f1 + f2 == 0:
        return 0.0
    if s1 == 0 or s2 == 0:
        return 0.0
    f1, s1, f2, s2 = float(f1), float(s1), float(f2), float(s2)
    # Expected values
    e1 = s1 * (f1 + f2) / (s1 + s2)
    e2 = s2 * (f1 + f2) / (s1 + s2)
    l1, l2 = 0, 0
    if e1 != 0 and f1 != 0:
        l1 = f1 * math.log(f1 / e1)
    if e2 != 0 and f2 != 0:
        l2 = f2 * math.log(f2 / e2)

    likelihood = 2 * (l1 + l2)
    if f2 / s2 > f1 / s1:
        likelihood = -likelihood
    return likelihood