def value_counts(values, sort=True, ascending=False, normalize=False,
                 bins=None, dropna=True):
    from pandas.core.series import Series, Index
    name = getattr(values, 'name', None)
    if bins is not None:
        try:
            from pandas.core.reshape.tile import cut
            values = Series(values)
            ii = cut(values, bins, include_lowest=True)
        except TypeError:
            raise TypeError("bins argument only works with numeric data.")
        result = ii.value_counts(dropna=dropna)
        result = result[result.index.notna()]
        result.index = result.index.astype('interval')
        result = result.sort_index()
        if dropna and (result.values == 0).all():
            result = result.iloc[0:0]
        counts = np.array([len(ii)])
    else:
        if is_extension_array_dtype(values) or is_sparse(values):
            result = Series(values)._values.value_counts(dropna=dropna)
            result.name = name
            counts = result.values
        else:
            keys, counts = _value_counts_arraylike(values, dropna)
            if not isinstance(keys, Index):
                keys = Index(keys)
            result = Series(counts, index=keys, name=name)
    if sort:
        result = result.sort_values(ascending=ascending)
    if normalize:
        result = result / float(counts.sum())
    return result