def _rank(sample):
    """
    Assign numeric ranks to all values in the sample.

    The ranks begin with 1 for the smallest value. When there are groups of
    tied values, assign a rank equal to the midpoint of unadjusted rankings.

    E.g.::

        >>> rank({3: 1, 5: 4, 9: 1})
        {3: 1.0, 5: 3.5, 9: 6.0}

    """
    rank = 1
    ranks = {}
    for k in sorted(sample.keys()):
        n = sample[k]
        ranks[k] = rank + (n - 1) / 2
        rank += n
    return ranks
