SPC Analytics ANALYZING ONLINE REVIEWS
Part I: Foundations · Mini-project

Mini-Project: Analyze 500 Reviews in 30 Minutes

Seven steps, thirty minutes, 500 hotel reviews, and no code: load the file, describe the ratings, contrast the vocabulary of the unhappy against the happy, measure sentiment, check that measure against the ratings you already have, and turn the result into three things somebody could do on Monday. It is a complete analysis and it is a small one. One file, one snapshot, and no revenue, occupancy, or booking outcome anywhere in it, which buys you a description and a hypothesis about where to spend effort, and does not buy you a cause.

6:13 lecture Deliverable: Your Thirty-Minute Analysis Notebook and Brief 7 knowledge checks 4 hands-on activities
Step 1 of 9 Video
Watch

The lecture

Mini-project · 6:13

Mini-Project: Analyze 500 Reviews in 30 Minutes

Lecture video arrives here.

Watch it once through, then work the steps that follow.
Chapter 1
Key ideas

What this chapter argues

The chapter's own argument, distilled. If you read nothing else on this page, read this.

01

A complete analysis can be small, and you can have one in thirty minutes

The seven steps are a whole loop rather than a demonstration: load the data, describe the distribution of the outcome, contrast the text of the worst cases against the best, build a measure, check that measure against something you already hold, and convert the result into three things a manager could act on. None of it requires you to write code. You type plain requests to Gemini in Colab and your job is the part that cannot be handed over: specifying what to compute, reading what came back, and deciding whether it means anything. Every chapter after this one deepens exactly one of these steps instead of replacing it. Chapter 5 takes the single lexicon of Step 5 seriously, with aspect sentiment, topic models, and validation. The panel and causal chapters take on the outcome variable this file does not have. Running the small version first is what lets you recognize which step each later method is repairing.

02

Loading is the first measurement, and the row count is what you check everything else against

Step 1 asks for three things and each has a job. The first five rows show whether the text arrived intact instead of mangled by the upload. The full list of column names tells you what you actually hold: review_id, hotel_id, date, rating, review_text, traveler_type, and platform. And the total number of rows is the control total for every step that follows, because a filtered count that cannot be reconciled with it is a pipeline problem rather than a finding. The two failures this step invites are both mundane. The file cannot be found because the upload did not finish, which is fixed by confirming the upload and reloading with the row count reported back. Or the rating column arrives as text like '1 star', in which case counting it silently produces nonsense, and the fix is to list the columns and make rating numeric before anything is counted.

03

The skew is the finding, and the mean is the worst summary of it

On this file the ratings run 1 star 50 (10 percent), 2 star 50 (10 percent), 3 star 65 (13 percent), 4 star 135 (27 percent), and 5 star 200 (40 percent), with a mean of 3.77. The shape is left-skewed: 27 plus 40 percent of the file sits in the two top bins, over a smaller floor of complaints, and the middle is thin. Two consequences follow. First, the mean of 3.77 falls in the sparsest part of the distribution, so it describes almost no actual review and it hides both the mass of satisfied guests and the floor of angry ones; the shape is the result, not the average. Second, the 1 and 2 star reviews are 100 rows in total and they are the entire raw material for Step 3, so the complaint word list is built from 100 reviews while the praise list in Step 4 is built from 335. That asymmetry is worth remembering later, when the complaint themes are the ones you are tempted to act on.

04

Two word lists are worth more than one, and the tokens in both are the warning

Step 3 filters to the 1 and 2 star reviews, strips filler words, and counts the 15 most frequent meaningful terms. Step 4 does the same for the 4 and 5 star reviews. Neither list is the analysis; the contrast is. Read together, the low side names slow check-in and service, housekeeping failures, thin walls and noise, air conditioning that does not work, and a sense of being overpriced. The high side names friendly and helpful staff, a good breakfast, quiet rooms and a good night's sleep, and good value. One is a fix list and the other is what you protect while fixing. The caveat is visible in the output itself: 'check' sits in the top 15 of both lists, at 71 on the positive side and 24 on the negative side, and terms like 'room', 'stay', and 'get' are frequent without carrying any direction at all. A count locates candidate themes. It does not name them. The naming is your reading of the text, and it is defensible only when you can point at reviews.

05

Sentiment is a measurement you have to be able to explain

Step 5 does not just ask for a score. It asks for VADER's compound score computed for every review, stored in a named column called sentiment_score, summary statistics for that column, and an explanation of what the values mean on the -1 to +1 scale. That last clause is the point: a number you cannot explain is a number you cannot defend, and the reason to reach for a fixed lexicon here is that it is fast and transparent, not that it is accurate. VADER assigns scores to words and combines them by rule. It has never seen a hotel, it does not know that thin walls is a complaint in this domain, and it treats a five word review with the same machinery as a five hundred word one. Those are the terms of the trade you make when you turn a text column into a numeric one inside a single prompt, and stating them is part of reporting the number.

06

The staircase flattens at both ends, and that is the method, not your mistake

Grouping sentiment_score by rating on this file gives 1 star -0.46, 2 star -0.42, 3 star +0.06, 4 star +0.86, and 5 star +0.86. It rises overall and it is nearly flat at both extremes: 1 and 2 stars barely differ, and 4 and 5 stars are almost identical. An uneven staircase here is not an error to fix. Three mechanisms produce it. Saturation, because VADER scores words rather than your 1 to 5 scale, so once a review is clearly positive more praise cannot push the compound score much past about +0.85. Negation and mixed sentiment, because phrases like 'the room was not bad' or 'great location but filthy bathroom' are handled crudely, so the flip gets missed or competing cues average into something middling. And sarcasm, very short reviews, and domain slang, which are weak spots of any fixed lexicon. Notice which end the saturation argument is stated for: it is written as a ceiling on praise, so whether the same mechanism produces the flatness between 1 and 2 stars is something to check in your own output rather than assume.

07

When stars and sentiment disagree, you are holding a reading queue and a Monday action

The practical rule is that VADER is a fast, transparent first pass that correlates with the rating, not a replacement for it. Which means the aggregate agreement is not the interesting part; the disagreements are. A review whose text scores positive while its rating is 1 star is a signal to go and read the text, and Step 7 turns that straight into an operating procedure: flag it for a human look before anyone acts, because it may be a mis-rating or part of a review bombing burst rather than a genuine complaint. This is also where the course's habit of using a result twice begins. One finding, two sentences. As a paper sentence: lexicon sentiment and star ratings diverge systematically at the extremes of the scale, which constrains how sentiment can serve as a proxy for satisfaction. As a Monday sentence: before we act on a one star review, somebody reads it. Chapter 5's validation checklist is the long form of the same discipline.

08

Thirty minutes buys a description and a hypothesis, not a cause

Look at what is not in this file. No revenue, no occupancy, no repeat booking, no cost of a complaint: no outcome variable of any kind. There is one snapshot, and although hotel_id and platform are both present, no step splits the data by either, so every result describes the pooled file rather than a hotel or a platform. That fixes a ceiling on what Step 7 can claim. Housekeeping being the most mentioned theme in the low star reviews is a description you can defend from your own counts. Fixing housekeeping will raise our ratings is a hypothesis. Fixing housekeeping will raise revenue is not supported by anything in the thirty minutes at all, because most mentioned is not most costly and a single cross section contains no comparison. The Learning Check attached to this lab is the same point in one line: a model that describes a pattern is not a model that explains why the pattern exists, and longer reviews being associated with lower ratings does not mean length drives the rating.

Do it yourself

Load it, count it, and refuse the AI's sentence

Data for this lesson
sample_hotel_reviews.csv
Copy this line
pd.read_csv("https://raw.githubusercontent.com/jeong-yeol/AOR_with_AI/main/data/samples/sample_hotel_reviews.csv")

Every file the course uses, with what is in each one, is on the data page.

No sample answers here: your output, your interpretation, is the exercise.

This is Steps 1 and 2, and it is where every checkable number in the rest of the lab comes from. Open a fresh Colab notebook with Gemini enabled and upload sample_hotel_reviews.csv from the companion data. Before you type anything, write two things on paper: how many rows you expect the file to have, and which of its columns you expect pandas to treat as numeric. You are going to compare the output against your own expectation rather than simply reading it.

Copy this prompt
Act as a careful data analyst working in a Google Colab notebook. I have uploaded a file named [the filename exactly as it appears in your Colab file browser, normally sample_hotel_reviews.csv]. Do not summarize or interpret anything until you have reported all of the following, in this order.

First, load the file into a pandas DataFrame and show me the first 5 rows exactly as they are, cleaning nothing.
Second, list every column name with the data type pandas assigned to it, and say explicitly whether the rating column is numeric or text. If it is text, stop there, tell me, and show me the command that converts it before you go on.
Third, report the total number of rows, and the number of missing values in each column.
Fourth, using the rating column, give me a frequency table of how many reviews gave each star rating, with both the count and the percentage of the total, and draw a bar chart of those counts.
Fifth, report the mean rating and the modal rating, and describe the shape of the distribution in plain English for someone with no statistics background. Name the skew and say which direction the thin tail runs.

Then three constraints. Reconcile your own numbers: the star rating counts must sum to the total row count, and if they do not, say so plainly instead of smoothing it over. Tell me which columns in the file you have not touched, and state what a reader would be wrong to conclude from a distribution of [the number of reviews you expect the file to hold] reviews about hotel guests in general. And do not tell me what any of this means for a hotel; I have not asked you that yet, and I want the description separated from the interpretation.

Paste it into your own ChatGPT, Claude, or Gemini window and run it. Replace anything in square brackets with your real numbers first.

Do it yourself

Two word lists, and the words that betray them

This is Steps 3 and 4 run together, because separately they are just word counting. The contrast between the low star vocabulary and the high star vocabulary is the analysis. Keep the notebook from the first activity open so the DataFrame is still loaded. Before you run the prompt, write down the three themes you expect to dominate the complaints in a hotel file and the three you expect to dominate the praise. Committing first is what makes the output informative instead of agreeable.

Copy this prompt
Continue in the same notebook, working with sample_hotel_reviews.csv. Act as a text analyst who is skeptical of word counts.

First, filter the dataset to only reviews with 1-star or 2-star ratings, report how many reviews that leaves, then take the review_text column, remove common English filler words such as 'the', 'and', 'a', and show me the 15 most frequent meaningful words with their counts.
Second, do exactly the same for reviews with 4-star or 5-star ratings, again reporting how many rows the filter leaves.
Third, print the tokens that appear in both top 15 lists, with the count each one carries on each side, and label them as uninformative on their own.
Fourth, for each list, group the remaining words into no more than four candidate themes, and for every theme quote two short excerpts from actual reviews inside that rating band that justify it. If a theme cannot be supported with a quotation, drop it and tell me you dropped it.
Fifth, say which of these candidate themes I could defend from the counts alone and which ones depend entirely on your reading of the text.

Here is what I expected to see in the complaints before I ran this: [write the three complaint themes you committed to]. For each one, say whether the counts support it, contradict it, or are simply silent on it. Do not soften a contradiction in order to agree with me. Finally, name one specific thing these two lists cannot tell me about this hotel data, and make it specific to word frequency rather than a generic caveat about text analysis.

Paste it into your own ChatGPT, Claude, or Gemini window and run it. Replace anything in square brackets with your real numbers first.

Do it yourself

Measure sentiment, then test the excuse for its flat ends

This is Steps 5 and 6 plus the teaching note, and it is where you stop being a consumer of the number. You have been told in advance that average sentiment by rating is not a clean rising staircase and that saturation is one reason for it. An explanation you accept because it was printed for you is not an explanation you have checked. Keep the notebook open; you will need sentiment_score, the rating column, and the raw review text side by side.

Copy this prompt
Continue in the same notebook with sample_hotel_reviews.csv. Act as a measurement specialist who separates what the data shows from what the tool does.

First, for every review calculate a VADER compound sentiment score and save it as a new column called sentiment_score. Report summary statistics for that column and explain what the values mean on the -1 to +1 scale, in language a reader with no statistics background could follow.
Second, group the reviews by star rating, report the mean sentiment_score at each rating level, and chart it.
Third, test the saturation account rather than asserting it. For the 4-star and 5-star bins, report how many reviews and what share have a sentiment_score above [choose a high threshold, for example 0.85], and how many are above 0.95. Then do the mirror image at the other end: for the 1-star and 2-star bins, report how many and what share fall below the negative counterpart of that same threshold. Say whether a ceiling on positive scores and a floor on negative scores are equally well supported by these counts, and if they are not, name which end is left unexplained.
Fourth, list the [how many, for example 10] reviews with the largest disagreement between rating and sentiment in each direction, and print the full text of each one.
Fifth, for each of those reviews, classify the likely cause as negation, mixed sentiment inside one review, sarcasm, a very short review, domain specific wording, or a rating that does not match its own text. Where the text alone cannot decide between two causes, say so and refuse to choose.
Sixth, state in one sentence what a strong overall correlation between sentiment_score and rating would license me to claim, and what it would not.

Do not adjust any score to make the chart look tidier, and do not describe the flat ends as an error.

Paste it into your own ChatGPT, Claude, or Gemini window and run it. Replace anything in square brackets with your real numbers first.

Do it yourself

Three recommendations and the sentence you are not allowed to write

This is Step 7, the moment a number you produced becomes something somebody does, and it is also where the thirty minutes runs out of authority. Have your own outputs in front of you: the rating distribution, both word lists, the mean sentiment by rating, and the disagreeing reviews you read. You will paste your own numbers rather than the file, so that every recommendation is tied to something you actually ran and can find again.

Copy this prompt
Act as two people in turn. First an analyst briefing a hotel manager who has thirty minutes and a budget, then a skeptical journal reviewer reading the same brief.

Here is everything my analysis of sample_hotel_reviews.csv produced. Rating distribution: [paste your frequency table and the mean]. Most frequent meaningful words in the 1-star and 2-star reviews: [paste your list with counts]. Most frequent meaningful words in the 4-star and 5-star reviews: [paste your list with counts]. Mean sentiment by star rating: [paste your numbers]. Reviews where rating and sentiment disagreed: [paste one or two, including the text].

As the analyst, write three concrete recommendations a hotel manager could act on. Each one must name the specific number or word from my output that supports it, and each must come in two versions: one sentence as it would appear in a research paper, and one sentence as it would appear in an instruction to a department head for Monday morning. Refuse to write any recommendation you cannot tie to a number I gave you, and where you refuse, tell me what number you would have needed.

Then switch roles. As the reviewer, do four things. Name, for each recommendation, the strongest claim my data supports and the claim I am most likely to overstate it into. Tell me what this file does not contain that the recommendations quietly assume, bearing in mind that there is no revenue, occupancy, or repeat booking measure in it and that no step split the data by the hotel_id or platform columns. Give me one rival explanation for the dominant complaint theme that has nothing to do with hotel operations. And write out the sentence I am not allowed to write: the causal claim a thirty minute descriptive analysis would tempt a reader into, phrased the way I would be likely to phrase it, so that I can recognize it in my own draft later.

Paste it into your own ChatGPT, Claude, or Gemini window and run it. Replace anything in square brackets with your real numbers first.

Knowledge check

Did the chapter land?

Every answer comes from this chapter. Pick one; a wrong pick tells you where to look and lets you try again.

  1. 01On sample_hotel_reviews.csv the star ratings fall 50, 50, 65, 135, and 200 from 1 star to 5 stars, with a mean of 3.77. What is the defensible reading of that shape?

  2. 02Average VADER sentiment by rating on this file runs 1 star -0.46, 2 star -0.42, 3 star +0.06, 4 star +0.86, and 5 star +0.86. What should a reader conclude?

  3. 03Why do enthusiastic 4 star and 5 star reviews end up with almost identical VADER compound scores?

  4. 04One review in your output carries a 1 star rating and a clearly positive sentiment_score. What does the chapter tell you to do with it?

  5. 05After thirty minutes on this file, which claim is actually licensed?

  6. 06The token 'check' appears in the top 15 of both word lists, at 71 in the 4 and 5 star reviews and 24 in the 1 and 2 star reviews. What follows from that?

  7. 07Step 1 asks for the total number of rows before any analysis begins. What is that number for?

Question 1 of 7
0 of 7 correct Answer to see how you did
Deliverable

Your Thirty-Minute Analysis Notebook and Brief

A Colab notebook that runs all seven steps on sample_hotel_reviews.csv, plus a one page brief carrying three recommendations, each tied to a number you produced and written twice, once as a paper sentence and once as a Monday sentence. It closes with one line naming what the analysis does not license, and it is the smallest complete thing this course asks you to make.

Next step

Want a read on what you just built?

Send us what you just built.

You now have your thirty-minute analysis notebook and brief for your own data. Paste it below and we will read it and write back with what we would tighten first: the question, the identification, or the measurement. No charge and no pitch, and if your design is already sound we will say that instead.

Goes to Jeong-Yeol Park directly. Nothing is published, and your notes stay on this device unless you press send.