def produce_frequency_explorer(corpus,
                               category,
                               category_name=None,
                               not_category_name=None,
                               term_ranker=termranking.AbsoluteFrequencyRanker,
                               alpha=0.01,
                               use_term_significance=False,
                               term_scorer=None,
                               not_categories=None,
                               grey_threshold=1.96,
                               y_axis_values=None,
                               frequency_transform=lambda x: scale(np.log(x) - np.log(1)),
                               **kwargs):
    '''
    Produces a Monroe et al. style visualization, with the x-axis being the log frequency

    Parameters
    ----------
    corpus : Corpus
        Corpus to use.
    category : str
        Name of category column as it appears in original data frame.
    category_name : str or None
        Name of category to use.  E.g., "5-star reviews."
        Defaults to category
    not_category_name : str or None
        Name of everything that isn't in category.  E.g., "Below 5-star reviews".
        Defaults to "Not " + category_name
    term_ranker : TermRanker
        TermRanker class for determining term frequency ranks.
    alpha : float, default = 0.01
        Uniform dirichlet prior for p-value calculation
    use_term_significance : bool, True by default
        Use term scorer
    term_scorer : TermSignificance
        Subclass of TermSignificance to use as for scores and significance
    not_categories : list
        All categories other than category by default.  Documents labeled
        with remaining category.
    grey_threshold : float
        Score to grey points. Default is 1.96
    y_axis_values : list
        Custom y-axis values. Defaults to linspace
    frequency_transfom : lambda, default lambda x: scale(np.log(x) - np.log(1))
        Takes a vector of frequencies and returns their x-axis scale.
    Remaining arguments are from `produce_scattertext_explorer`.'
    Returns
    -------
        str, html of visualization
    '''

    if not_categories is None:
        not_categories = [c for c in corpus.get_categories() if c != category]
    if term_scorer is None:
        term_scorer = LogOddsRatioUninformativeDirichletPrior(alpha)

    my_term_ranker = term_ranker(corpus)
    if kwargs.get('use_non_text_features', False):
        my_term_ranker.use_non_text_features()
    term_freq_df = my_term_ranker.get_ranks() + 1
    freqs = term_freq_df[[c + ' freq' for c in [category] + not_categories]].sum(axis=1).values
    x_axis_values = [round_downer(10 ** x) for x
                     in np.linspace(0, np.log(freqs.max()) / np.log(10), 5)]
    x_axis_values = [x for x in x_axis_values if x > 1 and x <= freqs.max()]
    # y_axis_values = [-2.58, -1.96, 0, 1.96, 2.58]
    frequencies_log_scaled = frequency_transform(freqs)  # scale(np.log(freqs) - np.log(1))

    if 'scores' not in kwargs:
        kwargs['scores'] = get_term_scorer_scores(category,
                                                  corpus,
                                                  kwargs.get('neutral_categories', False),
                                                  not_categories,
                                                  kwargs.get('show_neutral', False),
                                                  term_ranker,
                                                  term_scorer,
                                                  kwargs.get('use_non_text_features', False))

    def y_axis_rescale(coords):
        return ((coords - 0.5) / (np.abs(coords - 0.5).max()) + 1) / 2

    # from https://stackoverflow.com/questions/3410976/how-to-round-a-number-to-significant-figures-in-python
    def round_to_1(x):
        if x == 0:
            return 0
        return round(x, -int(np.floor(np.log10(abs(x)))))

    if y_axis_values is None:
        max_score = np.floor(np.max(kwargs['scores']) * 100) / 100
        min_score = np.ceil(np.min(kwargs['scores']) * 100) / 100
        if min_score < 0 and max_score > 0:
            central = 0
        else:
            central = 0.5
        y_axis_values = [x for x in [min_score, central, max_score]
                         if x >= min_score and x <= max_score]
    scores_scaled_for_charting = scale_neg_1_to_1_with_zero_mean_abs_max(kwargs['scores'])
    if use_term_significance:
        kwargs['term_significance'] = term_scorer

    kwargs['y_label'] = kwargs.get('y_label', term_scorer.get_name())

    kwargs['color_func'] = kwargs.get('color_func', '''(function(d) {
	return (Math.abs(d.os) < %s) 
	 ? d3.interpolate(d3.rgb(230, 230, 230), d3.rgb(130, 130, 130))(Math.abs(d.os)/%s) 
	 : d3.interpolateRdYlBu(d.y);
	})''' % (grey_threshold, grey_threshold))

    return produce_scattertext_explorer(corpus,
                                        category=category,
                                        category_name=category_name,
                                        not_category_name=not_category_name,
                                        x_coords=frequencies_log_scaled,
                                        y_coords=scores_scaled_for_charting,
                                        original_x=freqs,
                                        original_y=kwargs['scores'],
                                        x_axis_values=x_axis_values,
                                        y_axis_values=y_axis_values,
                                        rescale_x=scale,
                                        rescale_y=y_axis_rescale,
                                        sort_by_dist=False,
                                        term_ranker=term_ranker,
                                        not_categories=not_categories,
                                        x_label=kwargs.get('x_label', 'Log Frequency'),
                                        **kwargs)