'Remove too rare or too common features.
Prune features that are non zero in more samples than high or less
documents than low, modifying the vocabulary, and restricting it to
at most the limit most frequent.
This does not prune samples with zero features.'

def _limit_features(self, X, vocabulary, high=None, low=None, limit=None):

    if ((high is None) and (low is None) and (limit is None)):
        return (X, set())
    dfs = _document_frequency(X)
    tfs = np.asarray(X.sum(axis=0)).ravel()
    mask = np.ones(len(dfs), dtype=bool)
    if (high is not None):
        mask &= (dfs <= high)
    if (low is not None):
        mask &= (dfs >= low)
    if ((limit is not None) and (mask.sum() > limit)):
        mask_inds = (- tfs[mask]).argsort()[:limit]
        new_mask = np.zeros(len(dfs), dtype=bool)
        new_mask[np.where(mask)[0][mask_inds]] = True
        mask = new_mask
    new_indices = (np.cumsum(mask) - 1)
    removed_terms = set()
    for (term, old_index) in list(six.iteritems(vocabulary)):
        if mask[old_index]:
            vocabulary[term] = new_indices[old_index]
        else:
            del vocabulary[term]
            removed_terms.add(term)
    kept_indices = np.where(mask)[0]
    if (len(kept_indices) == 0):
        raise ValueError(u'After    pruning,    no    terms    remain.    Try    a    lower    min_df    or    a    higher    max_df.')
    return (X[:, kept_indices], removed_terms)
