๐Ÿ—‚๏ธ Review Theme Clusterer - Themes From Reviews & Tickets avatar

๐Ÿ—‚๏ธ Review Theme Clusterer - Themes From Reviews & Tickets

Pricing

Pay per event

Go to Apify Store
๐Ÿ—‚๏ธ Review Theme Clusterer - Themes From Reviews & Tickets

๐Ÿ—‚๏ธ Review Theme Clusterer - Themes From Reviews & Tickets

โšก Turn thousands of reviews, support tickets or survey answers into RANKED THEMES, not just a sentiment score. โœ… TF-IDF phrase weighting, blocking-based similarity clustering with no fixed k, top-distinguishing-term labels, volume/share/rating per theme, and rising/falling trend flags over time.

Pricing

Pay per event

Rating

0.0

(0)

Developer

mohamed alaya

mohamed alaya

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

Categories

Share

Review Theme Clusterer

Turn thousands of reviews, support tickets or survey answers into ranked themes โ€” not just a sentiment score. Everyone ships "68% positive, 32% negative." Almost nobody ships "battery life complaints are up 40% since March, here are the 12 reviews that say so." This Actor ships the second thing. Deterministic and lexical โ€” no LLM, no embeddings.

What it actually does

1. Text prep. Every review is normalised (lowercase, accents folded, punctuation stripped) and tokenised. Stopwords are removed with a RAKE-style rule: candidate phrases (unigrams, bigrams, trigrams) are only built from runs of consecutive content words, so a phrase never starts or ends on filler โ€” "the battery life is" yields battery, life, battery life, never the battery.

2. TF-IDF weighting. Term frequency per review, inverse document frequency across the whole corpus, so "great"/"product"/"would recommend" (in every review) don't drown out "battery life" or "customer service" (the phrases that actually distinguish reviews from each other).

3. Clustering with no fixed k โ€” and NOT O(nยฒ). This is the moat:

  • Inverted-index blocking. Each review's own top-K highest-weight terms become bucket keys. Only reviews that share a bucket are ever compared โ€” a review about tents is never compared against a review about headphones. Oversized buckets (a term so common it stopped discriminating) are skipped rather than allowed to reintroduce the O(nยฒ) blowup.
  • Verified cosine similarity. Candidate pairs from blocking are checked with an exact cosine similarity on the full TF-IDF vector โ€” blocking only proposes candidates, it never decides a match.
  • Average-link agglomeration. Verified pairs above the similarity threshold are merged strongest-first, but the merge test compares cluster centroids, not just the one seed pair. This resists the classic single-link "chaining" failure where ABC~D drags together a cluster where A and D share nothing in common.

4. Labelling. Each theme is labelled with its top distinguishing terms โ€” ranked by summed TF-IDF weight in the cluster, not raw word frequency โ€” so a theme reads as battery, life, drains, charge, overnight, not good, product, would.

5. Volume, share, rating, quotes. Each theme reports how many reviews it covers, what share of the corpus that is, the average rating of its members (if a rating field exists), and representative example quotes โ€” the reviews whose own TF-IDF vector is closest to the theme's centroid.

6. Trend over time. If a date field exists, each theme also gets a per-period (week/month) volume timeline and a rising / falling / stable flag, computed by comparing the first half of the observed timeline against the second half. This is the output that actually changes what a team does next โ€” not just "here's a topic" but "here's a topic that's getting worse."

Input

Pass reviews inline and/or sourceDatasetIds. Leave textField/ratingField/dateField empty and they're inferred from column names:

{
"reviews": [
{ "text": "Battery life is terrible, drains in a few hours.", "rating": 1, "date": "2026-01-05" },
{ "text": "Customer service was unhelpful and rude.", "rating": 2, "date": "2026-01-12" }
],
"similarityThreshold": 30,
"minThemeSize": 2
}

Thresholds are 0โ€“100 integers (Apify input schemas have no float type).

Output

theme rows โ€” one per cluster at or above minThemeSize, with label, terms (label terms plus their TF-IDF weight), volume, sharePercent, avgRating, exampleQuotes, and trend (null if no date field was found) ยท one other row aggregating reviews whose cluster fell below minThemeSize, so small groups are summarised rather than silently dropped ยท optional review rows tagging every input review with its assigned theme (includeReviewAssignments).

Honest limitations

  • This is lexical clustering, not semantic embeddings. It groups reviews that share distinguishing wording ("battery life", "battery drains fast"). It will not reliably merge a review that says "the phone dies too quickly" with one that says "poor battery life" โ€” there's no shared vocabulary for TF-IDF to weight. A true embedding model catches paraphrases; this does not, and does not pretend to.
  • English-oriented stopword list. Other languages will still cluster (TF-IDF and cosine similarity are language-agnostic) but candidate-phrase quality degrades without a matching stopword list.
  • Threshold tuning is a real trade-off, same as any clustering method: raise similarityThreshold for tighter, more numerous themes; lower it for broader, fewer themes, and expect more chaining risk near the low end even with average-link merging.
  • Trend detection is a first-half-vs-second-half comparison, not a statistical forecast. It is a deliberately simple, explainable "is this showing up more lately" signal, not a significance test.
  • Capped at 200,000 records per run.