Topic Modeling Nike Product Reviews: Marketing and Product Insights¶
Introduction¶
This project applies topic modeling to online reviews of Nike products to extract actionable insights for marketing and product development. The dataset comes from the Amazon Product Data repository, containing 8,327 distinct Nike products and 21,570 reviews.
Methods¶
Data Cleaning¶
Removed stopwords, punctuation, and numbers
Converted text to lowercase
Kept only words with ≥3 characters
Applied lemmatization to reduce words to base form
Vectorization¶
Reviews were vectorized using TF–IDF for text analysis.
Topic Modeling¶
Several topic counts were tested; 75 topics provided the most interpretable and granular results.
Each review was assigned to a topic, allowing both frequency-based and sentiment-based analysis.
Sentiment Analysis¶
Sentiments were labeled using TextBlob (positive, neutral, negative).
To improve clarity, review ratings (≥4 = positive, ≤2 = negative) were also used to validate sentiment results.
Results¶
Topic Distribution¶
Topic 63 had the largest volume with 1,264 reviews and an average rating of 3.79.
A pie chart highlights the top 5 and bottom 5 topics by review count.
Reviewer Patterns¶
Most prolific reviewer submitted 11 reviews.
Across the dataset, there were 20,423 unique reviewers, indicating a wide and diverse customer base.
Seasonality Trends¶
Review counts peak in spring and holiday season, with dips in late summer through winter.
Monthly review volumes were aggregated across all 75 topics to visualize seasonal demand.
Sentiment by Topic¶
Top 10 topics with the highest negative-to-positive sentiment ratios were identified.
Specific thematic categories (e.g., price, comfort, durability, design, fit, performance) were analyzed across topics.
Highlighted Topics
Topic 63 (Watches): Negative reviews mention band and battery issues; positives highlight satisfaction with watch purchases.
Topic 64 (Bags): Complaints about money, strap, and size. Lack of pockets is a recurring theme.
Topic 14 (Shoes – Sizing): Frequent mention of small and fit, even in positive reviews, suggesting sizing runs small.
Topic 0 (Shoes – Fit): Complaints about blisters and poor fit at the heel.
Topic 25 (Comfort): Positive reviews emphasize comfortable, but negatives indicate phrasing like not comfortable.
Product-Level Insights¶
Topic-level ASIN analysis shows divergence between products with positive vs. negative reviews.
Example: Topic 63 negatives focus on sandals and watches with sizing issues, while positives celebrate successful watch purchases.
Topic 14’s negative reviews consistently cite sizing issues across multiple product types, highlighting the need for clear sizing guidance.
Conclusion¶
Topic modeling and sentiment analysis reveal actionable insights for Nike product teams:
Marketing: Address customer concerns (e.g., “add pockets to bags,” “offer free sizing exchanges”).
Product Development: Improve sizing consistency, strap durability, comfort, and watch battery life.
Future Work:¶
Expand to product categories, customer segmentation, and deeper item-level review clustering.
Sentiment analysis on single words. if "watch strap" is always mentioned negatively, seeing it in both positive and negative reviews can indicate a truthful criticism.
Model used was LDA (Latent Dirichlet Allocation) which analyzes word frequencies and their distributions across reviews, taking a Bayesian approach and Dirichlet distributions to model the topic and word probabilities.
# ==========================
# 1. IMPORT LIBRARIES
# ==========================
import pandas as pd
import json
import ast
import gzip
import re
import itertools
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.decomposition import LatentDirichletAllocation
from sklearn.cluster import KMeans
from nltk.corpus import stopwords
import nltk
nltk.download('stopwords')
import warnings
warnings.filterwarnings('ignore')
[nltk_data] Downloading package stopwords to [nltk_data] C:\Users\forca\AppData\Roaming\nltk_data... [nltk_data] Package stopwords is already up-to-date!
import plotly.io as pio
pio.renderers.default = "notebook_connected"
import gzip
import ast # safe for parsing Python-literal dicts
import itertools
import pandas as pd
# ==========================
# 1. LOAD PRODUCT METADATA
# ==========================
META_FILE = "meta_Clothing_Shoes_and_Jewelry.json.gz"
nike_asins = []
with gzip.open(META_FILE, "rt", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue
try:
# Parse Python-style dict
data = ast.literal_eval(line)
categories = [c.lower() for c in itertools.chain(*data.get("categories", []))]
if "nike" in categories:
nike_asins.append(data["asin"])
except Exception as e:
print("Skipping line due to parse error:", e)
print(f"Found {len(nike_asins)} Nike ASINs")
# ==========================
# 2. LOAD REVIEW DATA
# ==========================
REV_FILE = "reviews_Clothing_Shoes_and_Jewelry.json.gz"
reviews_list = []
with gzip.open(REV_FILE, "rt", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line:
continue
try:
data = ast.literal_eval(line)
if data.get("asin") in nike_asins:
reviews_list.append({
"asin": data.get("asin"),
"reviewText": data.get("reviewText"),
"overall": data.get("overall"),
"reviewerID": data.get("reviewerID"),
"reviewTime": data.get("reviewTime")
})
except Exception as e:
print("Skipping line due to parse error:", e)
reviews_df = pd.DataFrame(reviews_list)
print(f"Found {len(reviews_df)} reviews for Nike products")
print(reviews_df.head())
Found 8327 Nike ASINs
Found 21570 reviews for Nike products
asin reviewText overall \
0 B0000V9K32 the colour i received is not blue as shown but... 3.0
1 B0000V9K32 Very cute and is really practical. Fits better... 5.0
2 B0000V9K3W The watch was exactly what i ordered and I got... 4.0
3 B0000V9K46 This product came promptly and as described, p... 5.0
4 B0000V9KNM Why isn't Nike making these anymore? I love t... 4.0
reviewerID reviewTime
0 ACT5DY536GISV 07 27, 2009
1 A3BVWMS9I8OH8U 12 26, 2009
2 A5RZS69KSJH00 10 24, 2009
3 A3F8O512N9UNVM 03 26, 2008
4 A2EAKTCKFRF7A4 11 16, 2011
# ==========================
# 3. TEXT CLEANING
# ==========================
from nltk.stem import WordNetLemmatizer
stop_words = set(stopwords.words('english'))
# Optionally add brand-specific stopwords like 'nike'
domain_stop_words = {'nike','shoe','shoes','product','pair','wear','feet','foot','running','run'}
stop_words = stop_words.union(domain_stop_words)
lemmatizer = WordNetLemmatizer()
def clean_text(text):
text = str(text).lower()
# Basic cleaning
text = re.sub(r'[^a-z\s]', '', text) # remove punctuation/numbers
# split and filter
words = [lemmatizer.lemmatize(w) for w in text.split()
if w not in stop_words and len(w) >= 3]
return ' '.join(words)
reviews_df['cleaned'] = reviews_df['reviewText'].apply(clean_text)
reviews_df
| asin | reviewText | overall | reviewerID | reviewTime | cleaned | |
|---|---|---|---|---|---|---|
| 0 | B0000V9K32 | the colour i received is not blue as shown but... | 3.0 | ACT5DY536GISV | 07 27, 2009 | colour received blue shown yellowcouldnt chang... |
| 1 | B0000V9K32 | Very cute and is really practical. Fits better... | 5.0 | A3BVWMS9I8OH8U | 12 26, 2009 | cute really practical fit better smaller wrist... |
| 2 | B0000V9K3W | The watch was exactly what i ordered and I got... | 4.0 | A5RZS69KSJH00 | 10 24, 2009 | watch exactly ordered got fast unfortunately b... |
| 3 | B0000V9K46 | This product came promptly and as described, p... | 5.0 | A3F8O512N9UNVM | 03 26, 2008 | came promptly described pleasure business themd |
| 4 | B0000V9KNM | Why isn't Nike making these anymore? I love t... | 4.0 | A2EAKTCKFRF7A4 | 11 16, 2011 | isnt making anymore love watch get lot complim... |
| ... | ... | ... | ... | ... | ... | ... |
| 21565 | B00KRENKNS | love it | 5.0 | AQOZEPFW4HTAR | 07 15, 2014 | love |
| 21566 | B00KXBJQ1A | They fit perfect and the are really light | 5.0 | A3H37LNK1EFP7C | 07 21, 2014 | fit perfect really light |
| 21567 | B00L01ML5K | The product was shipped in record speed! I lov... | 5.0 | A1N0CN53K1G2RW | 07 6, 2014 | shipped record speed love sneaker look feel aw... |
| 21568 | B00L2ADWCA | I like this item but they didn't have my size ... | 5.0 | AP318RPSIQQFA | 07 1, 2014 | like item didnt size tild alert |
| 21569 | B00L5K86LO | Love it ! | 5.0 | A1KBC812A7RSY9 | 07 20, 2014 | love |
21570 rows × 6 columns
# ==========================
# 4. VECTORIZE TEXT
# ==========================
# Using TF-IDF vectorization
vectorizer = TfidfVectorizer(max_df=0.95, min_df=5)
X = vectorizer.fit_transform(reviews_df['cleaned'])
# ==========================
# 5a. TOPIC MODELING (LDA)
# ==========================
num_topics = 75 # Adjust to your dataset and interpretability
lda = LatentDirichletAllocation(n_components=num_topics, random_state=42)
lda.fit(X)
# Function to display top words per topic
def display_topics(model, feature_names, no_top_words):
topics = {}
for topic_idx, topic in enumerate(model.components_):
top_words = [feature_names[i] for i in topic.argsort()[:-no_top_words - 1:-1]]
topics[topic_idx] = top_words
print(f"Topic {topic_idx}: {' '.join(top_words)}")
return topics
#feature_names = vectorizer.get_feature_names_out()
#topics = display_topics(lda, feature_names, 10)
# ==========================
# 5b. Display Top 4 Words per Topic AND store them
# ==========================
topic_top_words = {} # dictionary for mapping topic → top words string
for idx, topic in enumerate(lda.components_):
top_words = [vectorizer.get_feature_names_out()[i]
for i in topic.argsort()[-7:][::-1]]
topic_top_words[idx] = ", ".join(top_words) # store as string
print(f"Topic {idx}: {top_words}")
Topic 0: ['keeping', 'listed', 'barefoot', 'reading', 'modern', 'self', 'paint'] Topic 1: ['woman', 'often', 'men', 'comfortable', 'fit', 'vacation', 'washed'] Topic 2: ['glove', 'class', 'zumba', 'like', 'great', 'fit', 'love'] Topic 3: ['pink', 'color', 'combination', 'bright', 'hubby', 'love', 'green'] Topic 4: ['four', 'field', 'played', 'comfortable', 'originally', 'great', 'get'] Topic 5: ['wash', 'sock', 'reason', 'summer', 'washing', 'color', 'fun'] Topic 6: ['size', 'correct', 'fashionable', 'lighter', 'great', 'tad', 'fit'] Topic 7: ['future', 'thank', 'nephew', 'great', 'happy', 'love', 'asked'] Topic 8: ['flip', 'flop', 'pricey', 'father', 'shes', 'love', 'spike'] Topic 9: ['muy', 'que', 'para', 'los', 'excelente', 'producto', 'con'] Topic 10: ['boyfriend', 'play', 'basketball', 'ball', 'jacket', 'supportive', 'player'] Topic 11: ['enjoy', 'fake', 'worried', 'rip', 'lady', 'internet', 'ship'] Topic 12: ['great', 'fan', 'package', 'thrilled', 'huge', 'spring', 'gift'] Topic 13: ['picked', 'kinda', 'tighter', 'lil', 'stable', 'feel', 'balance'] Topic 14: ['ever', 'best', 'comfortable', 'ive', 'regret', 'considering', 'great'] Topic 15: ['good', 'training', 'cross', 'trainer', 'blister', 'site', 'support'] Topic 16: ['swoosh', 'thumb', 'fell', 'liked', 'cloth', 'shoelace', 'elastic'] Topic 17: ['advertised', 'rating', 'cold', 'chose', 'promptly', 'weather', 'compression'] Topic 18: ['shirt', 'expecting', 'lite', 'shin', 'recomiendo', 'splint', 'bien'] Topic 19: ['room', 'sister', 'backpack', 'school', 'penny', 'flexible', 'love'] Topic 20: ['others', 'boy', 'definately', 'active', 'adorable', 'recommend', 'cousin'] Topic 21: ['confortable', 'alot', 'soon', 'indoor', 'exact', 'love', 'fit'] Topic 22: ['golf', 'slipper', 'comfortable', 'person', 'bulky', 'sporty', 'fit'] Topic 23: ['birthday', 'gift', 'brother', 'earlier', 'opened', 'love', 'got'] Topic 24: ['worked', 'surprised', 'affordable', 'shipment', 'complement', 'cortez', 'well'] Topic 25: ['force', 'air', 'excelent', 'forever', 'combo', 'expected', 'man'] Topic 26: ['fitting', 'work', 'comfortable', 'thong', 'cannot', 'hour', 'forward'] Topic 27: ['insole', 'like', 'comfortable', 'toe', 'name', 'support', 'ive'] Topic 28: ['pocket', 'item', 'length', 'continue', 'authentic', 'space', 'loose'] Topic 29: ['okay', 'decent', 'besides', 'stretch', 'multiple', 'good', 'great'] Topic 30: ['present', 'particular', 'christmas', 'unfortunately', 'tshirt', 'red', 'boot'] Topic 31: ['rub', 'teenage', 'actual', 'vibrant', 'feeling', 'unique', 'styling'] Topic 32: ['shox', 'wider', 'wait', 'town', 'guy', 'careful', 'cant'] Topic 33: ['wonderful', 'spent', 'great', 'anymore', 'store', 'fit', 'comfortable'] Topic 34: ['marathon', 'treadmill', 'comfortable', 'exercise', 'promised', 'typically', 'sad'] Topic 35: ['recommend', 'anyone', 'great', 'delivery', 'job', 'highly', 'would'] Topic 36: ['grandson', 'thanks', 'he', 'bra', 'love', 'wallet', 'excited'] Topic 37: ['watch', 'band', 'battery', 'rate', 'one', 'time', 'heart'] Topic 38: ['width', 'colour', 'brought', 'wide', 'fit', 'size', 'great'] Topic 39: ['sunglass', 'lens', 'five', 'shopping', 'worst', 'case', 'star'] Topic 40: ['foam', 'yes', 'comfortably', 'website', 'memory', 'told', 'shower'] Topic 41: ['vomero', 'third', 'outlet', 'zoom', 'neutral', 'free', 'waste'] Topic 42: ['awesome', 'comfortable', 'jean', 'great', 'love', 'super', 'look'] Topic 43: ['beat', 'ended', 'uncomfortable', 'fair', 'dart', 'scheme', 'price'] Topic 44: ['apart', 'early', 'enjoyed', 'season', 'state', 'falling', 'sell'] Topic 45: ['held', 'everyday', 'difference', 'growing', 'impressed', 'shade', 'well'] Topic 46: ['breaking', 'cause', 'sock', 'fit', 'little', 'good', 'adjustable'] Topic 47: ['option', 'accurate', 'near', 'navy', 'adjust', 'seemed', 'generally'] Topic 48: ['bag', 'gym', 'clothes', 'hold', 'stuff', 'carry', 'perfect'] Topic 49: ['excellent', 'holding', 'football', 'wife', 'practice', 'good', 'fit'] Topic 50: ['value', 'orange', 'good', 'bright', 'per', 'jersey', 'great'] Topic 51: ['outfit', 'satisfied', 'totally', 'product', 'match', 'recomend', 'quality'] Topic 52: ['max', 'air', 'general', 'walking', 'basically', 'love', 'couple'] Topic 53: ['dirty', 'waiting', 'designed', 'white', 'sooner', 'mention', 'screen'] Topic 54: ['mom', 'cheaper', 'asking', 'breathe', 'loving', 'transaction', 'ahead'] Topic 55: ['team', 'daughter', 'dark', 'christmas', 'service', 'love', 'good'] Topic 56: ['watch', 'glass', 'face', 'hopefully', 'resistant', 'great', 'digital'] Topic 57: ['kid', 'packaging', 'somewhat', 'retro', 'faster', 'fitted', 'womens'] Topic 58: ['reasonable', 'stated', 'complain', 'price', 'terrible', 'believe', 'teenager'] Topic 59: ['ask', 'refund', 'xmas', 'sent', 'attention', 'get', 'received'] Topic 60: ['size', 'small', 'half', 'bigger', 'larger', 'fit', 'order'] Topic 61: ['cleat', 'happier', 'plan', 'wet', 'great', 'trail', 'pick'] Topic 62: ['amazing', 'find', 'anywhere', 'wow', 'glad', 'love', 'couldnt'] Topic 63: ['deal', 'kick', 'choose', 'real', 'dog', 'brown', 'good'] Topic 64: ['gotten', 'many', 'strong', 'shown', 'compliment', 'surprise', 'love'] Topic 65: ['watch', 'wrist', 'easy', 'button', 'activity', 'band', 'feature'] Topic 66: ['nice', 'please', 'customer', 'service', 'exchange', 'size', 'picky'] Topic 67: ['love', 'fit', 'exactly', 'perfect', 'great', 'comfortable', 'described'] Topic 68: ['purple', 'leg', 'fresh', 'sock', 'hate', 'great', 'comfortable'] Topic 69: ['photo', 'pegasus', 'date', 'late', 'poor', 'positive', 'narrower'] Topic 70: ['delivered', 'family', 'durability', 'waterproof', 'period', 'opinion', 'base'] Topic 71: ['jogging', 'slide', 'pic', 'uniform', 'comfortable', 'great', 'helped'] Topic 72: ['experience', 'wonderfully', 'ipod', 'recommendation', 'aware', 'tread', 'specifically'] Topic 73: ['sock', 'dry', 'warm', 'padding', 'strap', 'cut', 'boot'] Topic 74: ['pant', 'fit', 'smooth', 'great', 'love', 'ride', 'good']
# ==========================
# 5c. ASSIGN TOPICS TO REVIEWS
# ==========================
topic_assignments = lda.transform(X)
reviews_df['topic'] = topic_assignments.argmax(axis=1)
# Map the dictionary into the DataFrame
reviews_df["topic_top_words"] = reviews_df["topic"].map(topic_top_words)
reviews_df[["reviewText", "topic", "topic_top_words"]].head()
| reviewText | topic | topic_top_words | |
|---|---|---|---|
| 0 | the colour i received is not blue as shown but... | 64 | gotten, many, strong, shown, compliment, surpr... |
| 1 | Very cute and is really practical. Fits better... | 19 | room, sister, backpack, school, penny, flexibl... |
| 2 | The watch was exactly what i ordered and I got... | 59 | ask, refund, xmas, sent, attention, get, received |
| 3 | This product came promptly and as described, p... | 17 | advertised, rating, cold, chose, promptly, wea... |
| 4 | Why isn't Nike making these anymore? I love t... | 74 | pant, fit, smooth, great, love, ride, good |
# ==========================
# 6. SAMPLE INSPECTION
# ==========================
# Print a few reviews per topic with ASIN
for t in range(num_topics):
print(f"\n=== Topic {t} ===")
sample = reviews_df[reviews_df['topic'] == t].head(5)
for _, row in sample.iterrows():
print(f"ASIN: {row['asin']}, Review: {row['reviewText'][:100]}...")
=== Topic 0 === ASIN: B00012O2O2, Review: This is a great little watch for the price. I wear it to work and get lots of compliments. I am temp... ASIN: B000E8F2ZG, Review: This is a very nice and modern fashioned clock.The size is as espected. Highly recommended.... ASIN: B000G42Z2Q, Review: IT'S OK,... ASIN: B000J2F8GK, Review: TheyAreCofterbleAndNiceGoodGripAnd lookGreatKevenGarrantIs awesomeBecause he madeAwesomeShoe,,... ASIN: B000QU6VL6, Review: This is a great watch. I've never seen a design quite like it; it's quite an eye-catcher. It's als... === Topic 1 === ASIN: B0007RADZ8, Review: I FOUND THESE AND ORDERED THEM IN 2 DIFFERENT COLORS. MY SON LOVED THEM…THE PRICE WAS GREAT. H... ASIN: B0007RADZ8, Review: It's tough to find a great running shoe. I've been told throughout life that asics, new balance, an... ASIN: B0007RADZ8, Review: My son picked these out because of the color and style and he prefers Nike. Since he has wide feet,... ASIN: B0007TQLC0, Review: I love the watch, but had to return it, as the band was tiny, not just small. I have a 5 1/2" wrist,... ASIN: B000AI2NJI, Review: My daughter used this backpack 2 years in a row for 8th and 9th grade. She could have used it anothe... === Topic 2 === ASIN: B0007RADZ8, Review: good colors and good design, a very fair price, and i feel the shoes very confortables for jogging a... ASIN: B000TYS41E, Review: This is my 3rd one. It has all the features you need and conforms to your wrist like a glove.... ASIN: B000UCX0BO, Review: started to tear along the rim above the laces but not too bad and dont really mind it. shoes are com... ASIN: B0013UXIAK, Review: The shoe was brand new as posted, it fit well, and I am happy with my purchase. I would recommend th... ASIN: B0013UXIAK, Review: Wear a 7 1/2 got an 8 the shoe still felt too small but after a couple of daythe began to feel comfo... === Topic 3 === ASIN: B00019FWE4, Review: Nike Oregon Series Digital Super Watch - Black/Black - WA0024-001I purchased watch as a gift and my ... ASIN: B00019FWE4, Review: This is the second watch like this I have purchased and both are awesome. The watch is very comfort... ASIN: B0007RADZ8, Review: Gr8 fit, and feel. gr8 color combinations a very style strong shoe enjoying them. Would like to see ... ASIN: B000NKK5H0, Review: After using them for only a couple of weeks, I reached into my front coat pocket to find them broken... ASIN: B000SBW9OG, Review: Ordered as a gift for my brother in law and it fits him perfectly.He has been wearing them for a few... === Topic 4 === ASIN: B0006NGUE6, Review: Just about right for the price and actually it is exaclty what I was looking for, fits perfectly, gr... ASIN: B0007IA7O4, Review: Like many things I shop for on Amazon, I was looking for a pair of basketball shoes that were a good... ASIN: B0007RADZ8, Review: I really like Nike shoes and clothing. I'm comfortable with the shoes. It is good stuff to buy. I lo... ASIN: B0007RADZ8, Review: I heard reviews that Nike Revolution was not a commercial success. But when I saw this and read othe... ASIN: B0007RADZ8, Review: I bought these shoes originally for just wearing to the gym and playing tennis in. But these babies... === Topic 5 === ASIN: B0007SMKOO, Review: I liked it a lot! I live in Brazil and here cost +- 150,00 dollar..very expensive!... ASIN: B000A8BU6A, Review: watches were very nice. our clients loved them. boss loved them. nicely packaged.... ASIN: B000A8BUEC, Review: Ok ... for starters, I paid $38.00 for this watch ... this watch locally is very hard to even find &... ASIN: B000E8H0O2, Review: Moderately priced, stylish, attention to detail, not overwhelming, easy to operate. Would have been... ASIN: B000G42Z2Q, Review: Very light. Feel great and look nice as well. I only wish they came in a color that had black instea... === Topic 6 === ASIN: B00012O2S8, Review: i have owned one of these nike presto before and i have been thinking of buying a new one. i love th... ASIN: B00019FWE4, Review: I had this watch for exactly 12 DAYS, exactly. I liked the features and the size and weight etc. It ... ASIN: B0007RADZ8, Review: I ordered a 9.5 but when I tried them on they felt like a size ten I lay awake in regret wonder what... ASIN: B0007RADZ8, Review: Good running shoes to consider. It's light and fits well into the feet if you order the correct size... ASIN: B0007RADZ8, Review: Nice shoe, nice fit, Looks like a tennis ball got murdered to make the laces, so they'll see you com... === Topic 7 === ASIN: B0006NGUE6, Review: I find these shoes superior to another pair of Nike' golf shoes I previously owned. They fit well a... ASIN: B0007RADZ8, Review: I did measure my foot and it was 27 cmi orderd consequently in USA size but it should have been 1/2 ... ASIN: B000A8BU1U, Review: Thank you very much. Great price and fast shipping. Just what I needed.... ASIN: B000AORSVU, Review: Durable. Excellent quality. These were the 2nd pair as a gift for our son. He absolutely loves them.... ASIN: B000AORSVU, Review: Received these sunglasses very promptly. Everything was as advertised. Great SELLER!!! Would defi... === Topic 8 === ASIN: B0006NGUE6, Review: Good quality shoe that fit as expected. Shoe was purchased for my father and he loved the look and s... ASIN: B00073G928, Review: Bought as a gift for my running daughter. Directions are challenging and she's not thrilled with th... ASIN: B0007RADZ8, Review: Great shoe .... Better than what I expected! Great fit and also very comfortable! I would recommend ... ASIN: B000E93J64, Review: I bought this watch for my daughter who is on college. She has very small wrists and after trying ot... ASIN: B000E95LQK, Review: A light, very functional watch for both runners and fashion wear. I always get compliments on it's l... === Topic 9 === ASIN: B0006NGUE6, Review: Excelente producto, muy bonitos y comodos, los acabados y la presentación son excelentes, los... ASIN: B0007QZ0AW, Review: they was right on the money with this one, everything was what they said about the shoes in size, e... ASIN: B0007RADZ8, Review: very good, I am very satisfied with my purchase, recommended. compren sin duda.compren sin duda.comp... ASIN: B000A8BUCO, Review: Es un excelente monitor cardiaco pero al entrar al agua esto cambia completamente, a diferencia del ... ASIN: B000BJVY5K, Review: muy buena la presentaciony la talla pedida si inconvenietes un buen envio tal como lo que vi en la f... === Topic 10 === ASIN: B0007RADZ8, Review: i can train for hours and the shoes are still coolone of the best running shoes i had compare to all... ASIN: B0007SMKOO, Review: Great for playing sports or working out. Its small, it does its job, and comfortable.... ASIN: B000E8GZYI, Review: Cute, but you'd have to have the tiniest wrist in the world for it to fit comfortabtly... ASIN: B000E8H0O2, Review: only thing i don't like is the volume of the alarm, too low.... ASIN: B000EHIVAK, Review: It was very difficult to find a retailer that offered youth Nike watches. I appreciate the analog d... === Topic 11 === ASIN: B0006NGUE6, Review: These shoes turned out to be a very pleasant surprise. Excellent fit and comfort with everything yo... ASIN: B0007IA7O4, Review: They copied off of Kobe's shoes. The nike zoom atteroes on the other hand it has really good ankle ... ASIN: B0007RADZ8, Review: I love hess shoes. I do Taebo and run daily. These shoes are really light weight and can take a beat... ASIN: B000P6C3E0, Review: The shoe was in brand new condition and fit perfectly! I bought it as a gift and saved me lots of mo... ASIN: B000V4YZ1K, Review: They seem really small. And I don't have big feet. They aren't small (ladies) but not huge either. J... === Topic 12 === ASIN: B0000V9KRS, Review: I totally love this watch. It is much nicer and more beautiful than I thought when I bought it for a... ASIN: B0007RADZ8, Review: We were hoping to get a decent pair of NIKE's for the kid at a good price. These are not them. They ... ASIN: B0007RADZ8, Review: Purchased as a gift. Shoe fit very comfortably. Recipient LOVED them. Found new faith in buying s... ASIN: B000A8BTOI, Review: I loved the look of this watch that was on Amazon.com and ordered it. When I received it, the watch... ASIN: B000E8H0LA, Review: I bought this watch as a birthday gift for my husband and he loves it! It's beautiful, made well, a... === Topic 13 === ASIN: B0000V9KRI, Review: I mean, Roxy rocks, but I'm kinda dissapointed with the material. The purse lokks a lil' bit cheap.... ASIN: B000276C7Q, Review: I Love this watch. My only problem is it's fit. I have very small wrists. I wish there was a way ... ASIN: B0007RADZ8, Review: These shoes are great for exercising even running if that suits you. Great support, durable and my o... ASIN: B0007RADZ8, Review: Full disclosure is that I didn't purchase this shoe from Amazon, but I love it so much I wanted to l... ASIN: B0007RADZ8, Review: Comfortable, but could be wider through the toes. My big toe on each foot occasionally goes over the... === Topic 14 === ASIN: B0006NGUE6, Review: I was looking at more expensive shoes but thought I would give these a try. Great for a second pair ... ASIN: B0006NGUE6, Review: Best shoes I have ever owned. They look amazing!! And, they feel and fit perfectly. I would buy ag... ASIN: B0007QZ0AW, Review: This is the best shoe I have ever had. It's great looking, and wears like iron. Like you I have had ... ASIN: B0007RADZ8, Review: My teenage son is a fan of Nike shoes. I myself do not buy Nike footwear but he thinks they are ver... ASIN: B0007RADZ8, Review: Can't really complain about these shoes - they were relatively cheap, comfortable and semi-stylish..... === Topic 15 === ASIN: B00012O2MO, Review: My best friend has this watch and uses it for her work in the hospital. I loved it, so I got it and ... ASIN: B0001YMVTS, Review: The product never arrived. The vendor told me it was US postal service issue. The US postal service ... ASIN: B0007QZ0AW, Review: I purchased the Nike Womens VXT Cross Trainer Shoes, which are identical, with the exception of the ... ASIN: B0007RADZ8, Review: good product... ASIN: B0007RADZ8, Review: Nike Men's NIKE REVOLUTION 2 RUNNING SHOES 11 Men US (BLACK/WHITE/VARSITY). I use them to go to the ... === Topic 16 === ASIN: B0006NGUE6, Review: This product was exactly what I expected. The fit is comfortable and I would recommend this product ... ASIN: B0006NGUE6, Review: The shoes look great and the process was smooth and eazy. I recommend the buyer look closely at the ... ASIN: B0007RADZ8, Review: These felt a bit narrow and I ultimately ended swapping them out for the wider version.The shoes are... ASIN: B000A8BUDI, Review: So far I like the watch. It is a little big, but the features are easy to access and set. Not so sur... ASIN: B000G42Z2Q, Review: i like the product's material, it's so goodit's somewhat small for my right sidei dislike the shoela... === Topic 17 === ASIN: B0000V9K46, Review: This product came promptly and as described, pleasure doing business with them!-d... ASIN: B0006NGUE6, Review: Great fit your just have to buy a 1/2 size higher. The shoe very comfortable and grips well....its t... ASIN: B000SBW9OG, Review: sturdy and handy sandal for summer wear and around the pool or in the yard. I have had these for sev... ASIN: B0018E63MG, Review: The setup process is a little bit complicated. But after that, it works very well.... ASIN: B001G20EMA, Review: i did buy this shoes to go mountain bike riding love the shoes this is the type of shoes i like for ... === Topic 18 === ASIN: B000F9LFBE, Review: Nice watch. Elegant and comfortable. If you are a Arsenal fan, you have to get it, not kidding, just... ASIN: B000V4YZ1K, Review: very nice :D :D :D A+++++++++++++++++++++++++ lo mejor bien :3 d d d fdd df fd dc d df f... ASIN: B0013UXIAK, Review: I really like, I were spectacular, I can walk comfortable way, I fulfilled my expectations, thank yo... ASIN: B001718DSM, Review: Excelente la compra llego tal y cual como se esperaba lo recomiendo para futuras compras llego a la ... ASIN: B0018VL7TS, Review: The quality is so good on this shirt. My son loves it! It really is just as I expected and I am happ... === Topic 19 === ASIN: B0000V9K32, Review: Very cute and is really practical. Fits better on smaller wrists which is my case. I wear them every... ASIN: B0007RADZ8, Review: The fit and overall feel of these shoes are fantastic !! I would buy they again and recommend them t... ASIN: B0007RADZ8, Review: Nice confort , perfect size and incredible soft to run.the timing was pefect and the model is veru b... ASIN: B0007RADZ8, Review: Need to get them replace as the shoes run smaller than the size I typically use. Please get back to ... ASIN: B000A8BTO8, Review: My son, who is in middle school, loves this watch. The angle makes it easy to see, and it is pretty ... === Topic 20 === ASIN: B0006NGUE6, Review: Purchased this as a Christmas gift for my cousin as he just started picking up golf as a sport. The ... ASIN: B000V6W0IS, Review: it looks good, i think it is not a leather made(It is the reason i bought it), but still OK!... ASIN: B0010WOV8O, Review: Gift for my boyfriend. He like them. The rounding on the front was an intial concern, but he liked t... ASIN: B0013UXIAK, Review: he product is of excellent quality, and the time when the delivery has been made ​​very ... ASIN: B0013UXIAK, Review: Bought these for the style but the performance is what makes me give it 5 stars. Great hoops shoes, ... === Topic 21 === ASIN: B00012O2S8, Review: This is a great watch. It is comfortable and waterproof. I wore out the first one and purchased th... ASIN: B0007RADZ8, Review: Great shoes, received in excellent condition. Got a .5 size larger for a better fit. They fit fantas... ASIN: B0007RADZ8, Review: Its a pretty good shoe, to buy if you are looking for a pair of shoes to wear, if you are looking fo... ASIN: B0007RADZ8, Review: I love e The colors are very nice. Best quality. Nike is confortable sneakers and is perfect for run... ASIN: B0007RADZ8, Review: Good Shoes, meet my expectations, color is right, they are confortable and can be worn at the gym an... === Topic 22 === ASIN: B0001YMVVQ, Review: It's a great watch. I bought a Nike watch about a month earlier, loved it and bought this for a frie... ASIN: B0006NGUE6, Review: GREAT GOLF SHOES LOVE THEM A A A A A A A A A A A A A A A+... ASIN: B0006NGUE6, Review: Fast Shipping and was excellent deal. So far I have only worn it once, and it felt great. Didn't h... ASIN: B0006NGUE6, Review: Great shoes and my grandson loves them and will help him with his golf. He now no longer uses my sh... ASIN: B0006NGUE6, Review: I think it is a great golf shoe. comfortable and very functional, it does it's job. Hower, I am glad... === Topic 23 === ASIN: B0006NGUE6, Review: This item was a birthday gift for my husband. He loves them! He said they were about the most comfor... ASIN: B0006NGUE6, Review: I purchased these as a surprise for my boyfriend and he loves them. Says they are very comfy and hav... ASIN: B0007QZ0AW, Review: Shoes arrived clean and laced up, ready to go! They were in excellent condition from the box. They... ASIN: B0007RADZ8, Review: Its a nice shoes feet exactly.. That was gift of my brother.. I love the brand NIke...The other one... ASIN: B000E8H01K, Review: Great watch, great price. This is an awesome watch for weekend wear and sporting activities. It is... === Topic 24 === ASIN: B0002764JW, Review: Recieved in good shape and when expected. Just that the mens size was smaller than I expected. But... ASIN: B0006NGUE6, Review: Very please with my recent purchase of these Nike Golf Shoes. So far they seem to be holding up wel... ASIN: B0007RADZ8, Review: I wore them within ten minutes of delivery. Normally I don't do that, but they looked "cool"... ASIN: B0007RADZ8, Review: Nice styling. Like the bright lacings. Seem to be fine when running .Good value for the money. Easy ... ASIN: B0007RADZ8, Review: I think my brother gonna like it. So happy that I ordered it, and it is so affordable, I will recomm... === Topic 25 === ASIN: B0006TZU7S, Review: This watch is awesome but I barely got it and the display screen fell off!!! makes me mad.... ASIN: B0007RADZ8, Review: what I expected... ASIN: B0007RADZ8, Review: Just what I expected!... ASIN: B000BWLOH0, Review: Love this watch. Love this team. Comfortable, ergonomically correct, and well mad and durable. Th... ASIN: B000E8J5R2, Review: It is a good product of very good quality, very resistant and especially the mark sit down satisfie... === Topic 26 === ASIN: B00012O2MO, Review: It's cute, works reasonably well, but won't last long. Really cheap guts on this one. That's too b... ASIN: B0007RADZ8, Review: I'm a valet attendant, and since I'm running all the time, I go through running shoes pretty quickly... ASIN: B0007RADZ8, Review: The color is great, which is what attracted me to these shoes. Comfy & Light. Nice fit, as always N... ASIN: B0007RADZ8, Review: Love the fit and the shoes R all that was expected. Never had so many compliments. Look forward to m... ASIN: B0007RADZ8, Review: I purchased this as a gift for Christmas so I cannot comment on the shoe as of yet. But I really li... === Topic 27 === ASIN: B0006NGUE6, Review: comfortable low profile shoes that are great for holing you to the ground. Like the feel and certain... ASIN: B0006NGUE6, Review: Made out of cheap material in an effort to keep weight/cost down. No natural place for the upper to ... ASIN: B0007RADZ8, Review: These shoe gives good support for short distance running. I usually use this when I do less than 5 m... ASIN: B0007RADZ8, Review: The Nike Revolution 2 is a good shoe for light running days (1-3 miles). I have been training in thi... ASIN: B0007RADZ8, Review: These shoe gives good support for short distance running. I usually use this when I do less than 5 m... === Topic 28 === ASIN: B0007RADZ8, Review: Great fit for my feet. Wish they were a little higher but I expect that with running shoes.Love the ... ASIN: B000E8J4ZA, Review: I LOVE this watch! I am going to be purchasing more of the same watches in other colors. This has ... ASIN: B000FAG86K, Review: Could have a longer strap but its very good. Durable and can hold a good amount of items in it. I us... ASIN: B000FAK320, Review: My previous bag fell apart so I purchased this one. Nice construction, roomy whithout being too big... ASIN: B000G163DG, Review: Have not tried switching the lenses out -- but love the design and fit -- not too tight in the templ... === Topic 29 === ASIN: B0006NGUE6, Review: Just started playing golf, and I'm getting a little more serious about, so I wanted to pick up a pai... ASIN: B0007RADZ8, Review: Decent running shoes... ASIN: B000A8BU4M, Review: I wear it daily. the buttons depress accidentally though so it does not stay on the "time" screen.... ASIN: B000E8F2PG, Review: The plastic on the band is a bit harder than I expected. I thought it would be a softer feel... Ins... ASIN: B000EHP4XM, Review: Bought this as a gift for my preteen daughter. She loves it. It is almost too small though, it wou... === Topic 30 === ASIN: B00012O2S8, Review: First I have bought these watches in black colour for myself. I loved them! Then I decided to buy an... ASIN: B0007RADZ8, Review: The fit is excellent. The style is great. It is just the shoe for my workouts in the neighborhood.... ASIN: B0007RADZ8, Review: They were a present for my brother, who worn them and found them a little small, thus 4 stars and no... ASIN: B0007RADZ8, Review: Hi thereSize small, I bought another shoe brand Nike.I hope before apologeticThank you very much. . ... ASIN: B000A8BU8S, Review: Purchased this as a present for my teenage daughter and she loves it. She never wore a watch before ... === Topic 31 === ASIN: B0006NGUE6, Review: Very nice look & feel to the shoe. Soft comfortable sole. Now if only my swing would feel as comfort... ASIN: B0006NGUE6, Review: Very satisfied with the performance of the shoe in the field. Great fit, stability, and support when... ASIN: B0007RADZ8, Review: IT DOES NOT FEEL GREAT RUNNING COMPARES TO SHOES WITH SHOCKS . IT FELT FLAT LIJE WEARING SANDALS. BO... ASIN: B0009S1DMC, Review: I have the black w/ grey polarised lenses version, and I cannot be more pleased. As a runner, I app... ASIN: B000A8BTPM, Review: This is a good deal for the price I paid on Amazon. Even with $8.00 in shipping I still managed to s... === Topic 32 === ASIN: B000AI2QTK, Review: So GREAT.this was my first time usig amazon and this guy was so exelent.ThanksAntonio... ASIN: B000V4YZ1K, Review: Overall length is appropriate for my foot, but strap was way too tight. I have very average, medium ... ASIN: B000V6W0IS, Review: No chance to try them because they are too big and i did not wear them at all but the y look nice... ASIN: B001GULR14, Review: I returned them because I didn't like the way they looked on me. The company however was great with ... ASIN: B001IDPYNG, Review: I purchased these shoes for running. They are fablious! I will buy Nike shox again! They are sized a... === Topic 33 === ASIN: B00012O2RO, Review: I've found this watch very nice for a really good price (I needed it fast, so shipment was almost 50... ASIN: B0006NGUE6, Review: The shoes fit perfect. I love them glad I didnt pay attention to the comments about them being to na... ASIN: B0006NGUE6, Review: Very nice shoes. Might want to size up .5 your normal size. Plenty of comments about them on the l... ASIN: B0007RADZ8, Review: Looked better than i expected it fit wonderful and very cumffy u should buy best shoe good price why... ASIN: B0007RADZ8, Review: Already owned a pair so when they were getting worn out, one quick stop to Amazon and two days later... === Topic 34 === ASIN: B0006NGUE6, Review: Great shoes for an excellent price. The fit was perfect and the swoop was a bit darker than expecte... ASIN: B0007NDSA4, Review: amazing fit and it is so comfortable! didn't try this on before so i chose my side and it is true to... ASIN: B0007RADZ8, Review: Received these shoes and instantly fell in love. They fit perfect and look amazing!!! I've gotten ... ASIN: B0007RADZ8, Review: Very nice shoes...my son loved the color and comfort and the lite weight. Would recommend this shoe ... ASIN: B0007RADZ8, Review: This shoe is inaccurately sized at 11 1/2 - too small. I should have returned them, but thought they... === Topic 35 === ASIN: B0006NGUE6, Review: I have had these shoes for 3 months now and am really pleased with them!!! They are so comfortable a... ASIN: B0007RADZ8, Review: I really like the Nike Revolution 2 shoes. I run an average of 3 miles a day and have no complaints ... ASIN: B0007RADZ8, Review: I gave these shoes 5 stars because I really like the way they look and feel, very comfortable and ve... ASIN: B0007RADZ8, Review: Just what I needed. A quality shoe, good looking, well built & reasonably priced. the packaging was ... ASIN: B0007RADZ8, Review: this product is great nice design of the shoe and fits just right good for running and also for walk... === Topic 36 === ASIN: B0001YMVSY, Review: I bought this watch for my boyfriend for Christmas. He absolutely loves it and wears it all the time... ASIN: B0002764JW, Review: Great look, fit very well , you won't remember you have it until you need it , unisex, my wife and m... ASIN: B0007RADZ8, Review: Awesome product , thanks... ASIN: B000A8BTO8, Review: My grandson loved the Nike watch I gave him....it was a good purchase and the "in" thing for a sport... ASIN: B000E8H0BU, Review: I purchased this as a gift for my grandson. He enjoys it very much.... === Topic 37 === ASIN: B0000V9KRS, Review: when it arrived, it had a dead battery--SO, I had to invest in a new battery before I could guarante... ASIN: B00012O2MO, Review: I have used a similar watch (Arctic Blue) for several years. I love it. When I saw the same style ... ASIN: B00012O2S8, Review: About the price and product itself I have no complaints - it is nice, different, stylish, but it doe... ASIN: B00019FWE4, Review: I've had this watch for about a year and a half, and for a long time, I really loved it. The best th... ASIN: B0001YMVTS, Review: i had some problems with this order, the bill didn't arrive with the watch to the p.o. box and it co... === Topic 38 === ASIN: B0006NGUE6, Review: My husband liked the colors of these shoes, but the width was wrong. Did not have this shoe in a 7 w... ASIN: B0006NGUE6, Review: The shoes look good and comfortable. I have worn them for about half a dozen times now. The size is ... ASIN: B0007RADZ8, Review: These shoes are pretty sturdy and provide enough support for me (a heavy-ish runner). Nikes I buy t... ASIN: B0007RADZ8, Review: I love it, it is cool and comfortable. and the size fit as expected. and i claim the mail quickly.... ASIN: B0007RADZ8, Review: My son is hard to fit with shoes usually being too tight in the width or not fitting just right in t... === Topic 39 === ASIN: B0006NGUE6, Review: Excellent Shoes, very comfortable and nice. This case is wide and smooth when you are walking with t... ASIN: B0007RADZ8, Review: I've only taken these out running about 3 times so far, but I've liked them. They are comfortable an... ASIN: B0009RM2FU, Review: I forgot that I purchased these through Amazon. They lasted about 5 years of rugged use (beach volle... ASIN: B000A8BTO8, Review: wow!!! what a great watch. At first when I got it I thought it was a little hard to understand, but... ASIN: B000A8BTQ6, Review: I bought the watch on monday and got it on Saturday. Very good delivery!... === Topic 40 === ASIN: B0007RADZ8, Review: Awesome just what I ordered nike always has the best shoes Adidas suck because the are not nike qual... ASIN: B000E8CS30, Review: Product.not reliable.battery went flat after 6 months. Replaced new one went flat again in 2 weeks. ... ASIN: B000P6GKOO, Review: On the website nike.comi can get it for $70 when its not sold out.if it is i can get it for $110 usi... ASIN: B000SBW9OG, Review: These are great shoes. I use them for everything during the hot Texas summers. I highly recommend t... ASIN: B000V4YZ1K, Review: Soft as hell! Thought that these wouldn't be as great as the Adidas slippers I owned but these where... === Topic 41 === ASIN: B00012O2RO, Review: This is my third Nike Presto watch. It is easy to use and extremely easy to put on and take off. T... ASIN: B0001EKK1E, Review: I have problems with metal allergies, and I can't wear most watches. The Nike Presto watches I can w... ASIN: B0007R4SYK, Review: I've boughten and gone through two pair of these in a row. I haven't found any that I like the style... ASIN: B000E8F2PG, Review: I'm so disappointed with Nike. I got this beautiful watch for my birthday and can't wear it anymore... ASIN: B000E8H01K, Review: this watch is a durable, fantastic watch with a good reputation. thank you amazon!!!!!!!!!!1... === Topic 42 === ASIN: B0006MFAWA, Review: i think is a really good product for a low price... ASIN: B0007R4SYK, Review: These shoes look really nice and are very comfortable to wear. I was in need of new shoes when i bou... ASIN: B0007RADZ8, Review: awesomeeee shoes they are really comfortable and beautiful, They are one of my best collection of sh... ASIN: B0007RADZ8, Review: My dad loved his father day gift. Perfect size, color and style. He wears them everyday. He said it ... ASIN: B0007RADZ8, Review: I have a lot of pairs of running shoes, and these are a nice addition to my collection. To me, they ... === Topic 43 === ASIN: B00012O2W4, Review: This watch actually looks silver when viewed online, but when I received it I saw that it was in fac... ASIN: B0002IC3VY, Review: This is a goodlooking watch, but it doesn't have backlight as previous information detailed. I have ... ASIN: B0006NGUE6, Review: Shoes do not fit like traditional Nike golf shoes... almost felt defective. Ended up giving them aw... ASIN: B0006NGUE6, Review: I had to return the shoes after wearing them just two times, because they did not live up to the wat... ASIN: B0007RADZ8, Review: They fit right my father love them! The are very nice! They are very comfortables for walk! He like ... === Topic 44 === ASIN: B0007RADZ8, Review: green rubber is already falling off the shoe after 3 months of wearing them comfortable but glue the... ASIN: B0007RADZ8, Review: love them they are comfortable, light weight, and the colors are great, i recommend these sneakers t... ASIN: B000E8J52C, Review: I was looking for this color watch for months.Tried other web sites, but this watch was way over pri... ASIN: B000J2F8GK, Review: Order these shoes for my son on January 28th and received today January 31st.coming from Taiwan. My ... ASIN: B000J2F8GK, Review: Awesome shoes! Everything as expected specially for paying extra $50 for a pair of KD's. Will defini... === Topic 45 === ASIN: B0002QPMCI, Review: My wife wears this watch all the time and it never catches on her clothing or anything else she is r... ASIN: B0007RADZ8, Review: always love the look of nikes but never impressed with performance of shoe. i think they get cheape... ASIN: B000A8BUBU, Review: This is an excelent watch. I'm really impressed with all the resources included in it. Also, the des... ASIN: B000E8CR68, Review: I am very pleased with this product. i have been wanting it since it first came out of the market. I... ASIN: B000G42Z2Q, Review: Item is very comfortable to use for several hours everyday, fits right to size and looks very good n... === Topic 46 === ASIN: B0006NGUE6, Review: They fit, they are fairly priced, the quality is great, they work like a charm, they have interchang... ASIN: B0006NGUE6, Review: The shoes arrived just in time for a scheduled round of golf. The shoes were very comfortable and di... ASIN: B0006NGUE6, Review: They were a bit stiff at first but once they got broke in they are very comfortable. Recommend brea... ASIN: B0007RADZ8, Review: I was a little hesitant about buying sneakers online, fearing I might end up with some fakes. But na... ASIN: B0007RADZ8, Review: super comfy! best shoes I've bought in quite some time! nice and light, good breathability and comfo... === Topic 47 === ASIN: B0006NGUE6, Review: I have a wide foot so buying shoes over the internet is always a risk for me. These fit very nicely ... ASIN: B0006NGUE6, Review: I had a pair just like this for like 10 years, but got sick of gluing the bottom back on. Granted I ... ASIN: B0007RADZ8, Review: Too tight which makr it uncomfortable, I think the size may not be accurate. Esthetically it is not ... ASIN: B0007RADZ8, Review: I bought these at Academy sports for $50. The first day they were tight and I thought I was going to... ASIN: B0007RADZ8, Review: Shoes are too small. Understand that there is a free return. How do we go about returning them and ... === Topic 48 === ASIN: B0002BLHCW, Review: Perfect size gym back for a typical gym locker. Can hold a pair of sneakers, pants/shorts, towel, a... ASIN: B0007QZ0AW, Review: I bought 2. But two pair both Left and right looks some different.So sad. T.Tbut very comfort. and... ASIN: B000A8BUEC, Review: Everything was OK. I actually recommend.... ASIN: B000AI2QHW, Review: I love this bag. It's a perfect size and I use it all the time. It's also a good looking bag unlike ... ASIN: B000AI2VE0, Review: Great bag, but i wish it were a little bigger to accomidate my gym clothes/shoes.... === Topic 49 === ASIN: B0006NGUE6, Review: These shoes were very stiff when I first got them but they broke in quickly.Good pair to play in.... ASIN: B0007RADZ8, Review: bought these for supportive shoes after our daughter had ankle surgery. Great fit, great price, seem... ASIN: B0007RADZ8, Review: Is is a good shoe, I was playing football and I needed something comfortable for when we ran sprints... ASIN: B0007RADZ8, Review: excellent shoes, great quality and service, are as expected and i love this make are comfortable and... ASIN: B000BY55C8, Review: I bought this as a gift for my wife - she LOVES it!!!! Everyone in my household is happy with this w... === Topic 50 === ASIN: B0006821SK, Review: First of all, battery died prematurely twice. Both times it was replaced by a reputable jewler. Th... ASIN: B0006NGUE6, Review: These shoes lived up to my hopes after seeing the pictures on Amazon. The leather could be a little ... ASIN: B0007R4U5W, Review: Very pretty smart and tough, I hope to continue shopping at amazon, I love the Nike brand, are very ... ASIN: B0007RADZ8, Review: Stylish, great fit. Wish the one in the orange trim wasn't so expensive (and what's this all about t... ASIN: B0007RADZ8, Review: Stylish, great fit. Wish the one in the orange trim wasn't so expensive (and what's this all about t... === Topic 51 === ASIN: B0000V9KRI, Review: good price, very good material and excellent design, very useful for traveling, totally recomendatio... ASIN: B0006MFAWK, Review: I bought this for my 16 year old cousin, and I am sure it is going to be the perfect gift for her ..... ASIN: B0006NGUE6, Review: I purchased these for my husband, a new golfer. He says they are comfortable, and they look really s... ASIN: B0007RADZ8, Review: very good tennis, I love the nike brand is very good quality and presentation. I recommend it. would... ASIN: B0007RADZ8, Review: Did not fit so they have been returned as of Nov.27 2013. Waiting for confirmation that they have r... === Topic 52 === ASIN: B000BJVY5K, Review: If you're an air max fan, I recommend these ones. I love my old air max's and it was time for a new ... ASIN: B000E8H01K, Review: The "Nike Men's Hammer Watch" (#C0021-001) is freakin' AWESOME!!! It is pretty huge but I really lik... ASIN: B000E8H0BU, Review: I have had difficulty finding a watch for swimming. This has met all my needs. Of good size so eas... ASIN: B000G42Z2Q, Review: I've owned many Nikes before, but have never had a sneaker hurt the top of my foot like this. In the... ASIN: B000OFN364, Review: The Nike TRIAX Air Structure 10 I purchased had a very poorly made left shoe, leaning far to the lef... === Topic 53 === ASIN: B0001YMVSY, Review: It is oversized for my wrist. It will be fine to wear around but not for running which is what I bou... ASIN: B0007RADZ8, Review: Fit as expected. So far they are pretty comfortable to run in which is key for me getting out there.... ASIN: B0007RADZ8, Review: I can never find cool looking sneakers in wides in 13's.Oh wait i did.These are nice just fit snug.... ASIN: B000A8BTMK, Review: I bought this as a gift for my youngest daughter's birthday. She absolutely loves it! Of course my o... ASIN: B000A8BTQ6, Review: Tells time with giant numbers on screen. Rocks my socks off.... === Topic 54 === ASIN: B0007R6CAS, Review: My lady got these as a gift. I really like these shoes. I will drop hints about another pair I like... ASIN: B0007RADZ8, Review: It was great and my son was happy with his new Nike revolution shoes 10.5 men white color bought in ... ASIN: B0007RADZ8, Review: The entire transaction was great, easy to order, quick to ship and arrived faster than expected. I'... ASIN: B000E8H01K, Review: This was a gift, which the person loved, and I loved the price, $30.00 cheaper than everywhere else... ASIN: B000P6GKOO, Review: Great spring/summer shoe. Not really for running. Fits true to size but is also a soft mesh so there... === Topic 55 === ASIN: B00012O2O2, Review: This watch is ideal for a person with a very small wrist. Looks very nice but is light green not ca... ASIN: B00012O2RY, Review: Hello good evening, excellent product quality, comfortable, nice, good wreck 100% recommend them ver... ASIN: B00019WP6M, Review: This shirt is of good quality and logo of the team is large and striking.... ASIN: B0007RADZ8, Review: excellent quality, are accurate to the picture showing, Super Light, wonderful finish, ideal for wal... ASIN: B000E8CRZ4, Review: this was a great watch, excellent service. The order arrived on time and I love the watch.... === Topic 56 === ASIN: B00012O2LA, Review: I own three of these watches. They are perfect for an active lifestyle, water resistant, a chron to ... ASIN: B00012O2O2, Review: I had great hopes for this watch as I wanted a funky cool change for spring-- the colors do not cont... ASIN: B00012O2R4, Review: Very nice watch for a teenager, it has a pretty blue backlight and looks so nice when you wear it.... ASIN: B00019FWE4, Review: I'm on my 4th watch... I keep returning it due to poor design. The band keeps coming apart in the s... ASIN: B0001YMVTS, Review: Im happy with this watch so far. In my type of work I always need a durable watch. I used to be a bi... === Topic 57 === ASIN: B0007RADZ8, Review: fit somewhat tight but as expected! great buy, fast shipping and cheap price.... ASIN: B0007RADZ8, Review: The price was perfect and the shoes are very confortable. The packaging was in perfect conditions. I... ASIN: B0007RADZ8, Review: I have found men's sneakers fit me better than women's (I wear a 13.5 or 14 in women's - I'm 6 feet ... ASIN: B0007RADZ8, Review: No where as good as the Nike air I bought locally for less. Very disappointed in the shoe. I have ... ASIN: B000A8BU4M, Review: This watch is perfect for exercise, small, reliable, and has a lot option that you select. I recomme... === Topic 58 === ASIN: B0007RADZ8, Review: Since I purchased goods I need in Amazon, I think everything is good except COMBO SET YONEX Badminto... ASIN: B0007RADZ8, Review: I got these for my husband and he liked them. Theyre a lot lower than expected at the ankle, He thou... ASIN: B0007RADZ8, Review: These are a good looking pair of shoes, they fit well and feel pretty good and for a good price. My ... ASIN: B000E8F1WK, Review: I like this watch however it is a bit to thick for my wrist. When I wear it, the band gets in the wa... ASIN: B000FAG88S, Review: This bag is actually larger than I thought. You can really fit a lot into it. This would be good f... === Topic 59 === ASIN: B0000V9K3W, Review: The watch was exactly what i ordered and I got it very fast. Unfortunately it was a bit too big for ... ASIN: B0006NGUE6, Review: Great looking and really good feeling shoes. They are stable and comfortable. It's like playing in... ASIN: B0006NGUE6, Review: Sent wrong color shoes. Sent white when I ordered black but I had to use them anyway because of time... ASIN: B0007RADZ8, Review: The size was not right, but I would have returned them anyway as they arrived laced up, with sock fu... ASIN: B0007RADZ8, Review: Great shoes for the price, I work out 5 days a week doing weights and cardio. They are comfortable a... === Topic 60 === ASIN: B0001YMVSY, Review: Great watch, very comfortable, good size , it fits nice, good color, if you have bigger wrist be awa... ASIN: B0002164KC, Review: By far, the best pair of shoes I've ever owned. Well, you only need to know that their size is norma... ASIN: B0006MFAW0, Review: This watch is very cute. It is described as being a petite watch but that is a polite word for sayin... ASIN: B0006NGUE6, Review: I received these shoes last week. Aside from the usual break in period (stiffness), these shoes didn... ASIN: B0006NGUE6, Review: a good looking shoe but not to be recommended to buy unseen and untried. For the size on the shoe, i... === Topic 61 === ASIN: B0006NGUE6, Review: As comfortable if nor more than foot joy dryjoys. Have played a few rounds no issues. Might have to... ASIN: B000AYJLUQ, Review: This is the most comfortable mat that I have ever used. Has a great surface and I love the dual colo... ASIN: B000G42Z2Q, Review: I use these Nike Shoes for working out at the Gym. they feel lite and comfortable. They fit very wel... ASIN: B000J2F8GK, Review: This is a great shoe to either play basketball in or to wear with your street clothes I personally l... ASIN: B000P6FKAE, Review: As a sneaker collector, I am always on the prowl for Nike Dunks, so I was extremely happy to find th... === Topic 62 === ASIN: B0007RADZ8, Review: I am pretty active after my 9-5 with wight lifting, running, circuit traing and these shoes have bee... ASIN: B0007RADZ8, Review: They are great shoes for me to where anywhere and work in them numerous days a week. They are nice ... ASIN: B000AORSVU, Review: I'm very happy with my purchase. I where my sunnies everyday. I really like this style. I will buy t... ASIN: B000P6GKOO, Review: after a couple of months wearing them the suede pulled out of the sole and there is a blow-out hole ... ASIN: B000V4YZ1K, Review: I ordered this item for a co- worker son. She wanted to get them something but don't have a computer... === Topic 63 === ASIN: B0001EKJZG, Review: i had a brown one and wanted another. like the color purple a lot but would prefer the wristband "ho... ASIN: B0007RADZ8, Review: Not too big and not to small. Looks like not as the same as I expected, but I think it is not big de... ASIN: B000G42Z2Q, Review: These are, naturally, a good quality shoe, coming from Nike. They fit true to size and are very comf... ASIN: B000P6GKOO, Review: Great shoe for general use, not a real running shoe....very comfortable with or w/o socks. Perfect s... ASIN: B000P6GKOO, Review: PERFECT EVERYTHING!!!! THESE SHOES IS MY MUZZAFELKIN NEW FREEINDS YO. IF UZ UP 2 ME ID OWNZ LYK 200 ... === Topic 64 === ASIN: B0000V9K32, Review: the colour i received is not blue as shown but yellow.Couldnt change it because it was a birthday pr... ASIN: B0001EKJZG, Review: I love this watch and have it in a couple of other colors - when I saw I could get a pink one, I fig... ASIN: B0007RADZ8, Review: They are very comfortable and I've gotten lots of compliments from people. If you're looking for a g... ASIN: B0007RADZ8, Review: definitively I have not received what I needed color, color were wrong order. when he received my su... ASIN: B0007RADZ8, Review: It's like walking on air. These are so comfortable to wear and I love running in these! I've gotten ... === Topic 65 === ASIN: B00012O2O2, Review: I've had several of these watches in various colors and love them. The picture is very misleading. ... ASIN: B00012O2RE, Review: I purchased this for one of my teenage daughters as she has small wrists and really liked the look o... ASIN: B00012O2RY, Review: This is a beautiful watch, bigger than I thought it would be, which made me happy. The back light wo... ASIN: B00012O2SI, Review: I love this watch. Easy to wear to work and for every day. It is a great watch. I wish Nike still ... ASIN: B00012O2SI, Review: I am allergic to metal clasps so this bracelet type works well for me. This Nike line was discontin... === Topic 66 === ASIN: B0006NGUE6, Review: Very nice and comfortable golf shoes!! This was the only place I could find these to fit me. Will lo... ASIN: B0006NGUE6, Review: I'm a total amateur that's starting to understand the way the game is played, instead of just swingi... ASIN: B0007RADZ8, Review: Nice shoes!... ASIN: B0007RADZ8, Review: Very nice shoe and comfortable.... ASIN: B000E8J5N6, Review: This product is great for helping beginners improve their running, but it is not for the techno-phob... === Topic 67 === ASIN: B0001YMVVG, Review: The watch is great! Came in a few days and was in brand new condition, as expected.... ASIN: B0006NGUE6, Review: Very pleased with how easy it was. Purchase arrived in a very timely fashion...shoes fit very well ... ASIN: B0007RADZ8, Review: Just as expected. This pair is perfect for work and are very comfortable. Great price and great prod... ASIN: B0007RADZ8, Review: My husband said they are very comfortable and easy to walk in, which he does a lot of. They also loo... ASIN: B0007RADZ8, Review: They are very comfortable, they look exactly the same in the picture. My son was very happy and will... === Topic 68 === ASIN: B0000V9KRI, Review: I love this watch, i use every day, every where, to work, to go to the gym, pool, sports, etc. Eveth... ASIN: B0001EKJZG, Review: My GF loves purple and works in the NICU. This watch is perfect for that and she loves it. It comes ... ASIN: B0002IC3ZU, Review: I like the angle; makes it much easier to read. Numbers don't need to be stretched - get the one w/... ASIN: B00073G91Y, Review: Comfortable fit. Wore in the ocean and pool and worked great... ASIN: B0007RADZ8, Review: Got em for my hubbys birthday. He loves the darn things, super light weight, comfortable, easy to wa... === Topic 69 === ASIN: B0007TQLC0, Review: I love this watch and I wear it from Memorial Day to Labor Day. I wish I could find it in clear.... ASIN: B000A8BTPC, Review: I can not give a positive or negative opinion about the watch, as up to today I have NOT received it... ASIN: B000A8BU0Q, Review: This watch has been literally all over the world from the top of mountains to the bottom of the ocea... ASIN: B000E8J5B8, Review: This is quite possibly the best watch I've ever worn. It looks really stylish and everyone that sees... ASIN: B000G42Z2Q, Review: Amazing shoes, good for running, going to the gym and any physical exercise.The price was excellent ... === Topic 70 === ASIN: B00019WPTE, Review: This was a bday gift for one of my family members, who is of course a flyers fan. It got to him in g... ASIN: B0001YMVVG, Review: This watch is sporty, lightweight, easy to take on and off. I'm a nurse and wash my hands often so ... ASIN: B0006NGUE6, Review: These fit perfect and no break in period. I'm very happy with the comfort and looks of this shoe. Th... ASIN: B0007RADZ8, Review: After wearing these for about a month I can say a few things:Pros:- The shoes look fantastic and app... ASIN: B0007RADZ8, Review: great fit, comfortable, delivered on time. was looking for a comfortable gym shoe for my 15 year old... === Topic 71 === ASIN: B0006NGUE6, Review: They are confortable to wear and are of quality construction. They haven't helped my golf game thoug... ASIN: B0006NGUE6, Review: shoes fit great. exact color I wanted and it helped my golf game a lot and helped me drive 320 yards... ASIN: B0009RSNCQ, Review: Perfect fit, look, quality. Great for every day use including jogging or sports.So comfortable I for... ASIN: B000G42Z2Q, Review: When I recieved this item one of the silver lace loops (Which you can see in the picture) was ripped... ASIN: B000J2F8GK, Review: My son loves the shoes! Though we ordered them a bit too big....he still loves them and gets plenty ... === Topic 72 === ASIN: B000A8BU38, Review: This watch is very light and moves well with you in high action sports.I like the design of the band... ASIN: B000AI5NRW, Review: great bag. i have had this for a couple of years now and it has held up wonderfully. wouldn't expect... ASIN: B000P6GKOO, Review: -----The Good Stuff------great ventilation and cushioning-lightweight impact protection-really versa... ASIN: B000V4YZ1K, Review: the sandals fit great. But, wrong size. Ineed a 12 size to fit me. the 16 is longer than i need the... ASIN: B0013UXIAK, Review: You need to ask my child about these shoes..... wears them all the time, they do not leave his room ... === Topic 73 === ASIN: B0006NGUE6, Review: I purchased these as a gift for my son. He loved them. They fit well, he thought they were well ma... ASIN: B0007RADZ8, Review: Not to tight fitting, still had space to move foot around. Lightweight with enough air circulation t... ASIN: B000G3PT1G, Review: I play freshman football and I needed something to add to my uniform. These were perfect. The color ... ASIN: B000UQL1T8, Review: These boots are terrible! Yes they are stylish and comfortable but they are not waterproof what so e... ASIN: B000V4YZ1K, Review: Tight across the arches. Will hopefully stretch with time. Otherwise, they have very good constructi... === Topic 74 === ASIN: B0000V9KNM, Review: Why isn't Nike making these anymore? I love this watch, and I get a lot of compliments, questions f... ASIN: B0001YMVVQ, Review: This watch is great because it's different, comfortable, and simple. It doesn't have a timer or any... ASIN: B000E8H060, Review: Swanky sporting watch..got a true fit.I even purchased the gold its slightly different but just as n... ASIN: B000E8H0BU, Review: My dad wanted this watch for working out and playing sports after he saw it at Dicks Sporting Goods.... ASIN: B000G3PT1G, Review: not so good as i expected, it doesn't have the lable as the picture shows and extra strings are obvi...
13 topics¶
Topics 0, 2, 4, 5, 6, 8 → positive product themes (comfort, gym shoes, family gifts, socks).
Topics 7, 11, 12 → negative themes (fit issues, sizing, color expectations).
Topics 1, 9, 10 → niche products (Spanish reviews, watches, sandals/backpacks).
29 topics¶
Topics 0–8: Shoes and comfort are dominant.
Topics 9, 14, 16, 19: Accessories like watches and general appearance.
Topics 12, 22: Bags, hats, and sports gear.
Topics 15, 23: Food or non-shoe products (Spanish reviews or consumables).
Many topics reflect comfort, fit, and gift-giving as the main themes.
75 topics (most definitive)¶
Topic 0: Footwear comfort and fit problems, especially blisters and toe pain.
Topic 3: Shipping and delivery experience; speed and accuracy of orders.
Topic 5: Pain or discomfort from specific shoes (e.g., Airmax), often related to style or heat.
Topic 14: Apparel or shoe sizing issues; differences between expected and actual sizes.
Topic 19: Shoe durability, comfort, and balance; long-lasting wear concerns.
Topic 25: Running or jogging shoes; comfort and fit during workouts.
Topic 53: Customer service issues; returns, wrong shipments, and company responsiveness.
Topic 63: Watches; band fit, wrist comfort, and usability features.
Topic 70: Apparel colors; brightness and aesthetic appeal in shoes & clothing.
Topic 64: Gym bags; storage, pockets, and general usability.
Topic 49: Reviews in spanish
# ==========================
# 10. SAVE RESULTS
# ==========================
reviews_df.to_csv("nike_reviews_with_topics.csv", index=False)
df1= pd.read_csv("nike_reviews_with_topics.csv")
df1
| asin | reviewText | overall | reviewerID | reviewTime | cleaned | topic | topic_top_words | |
|---|---|---|---|---|---|---|---|---|
| 0 | B0000V9K32 | the colour i received is not blue as shown but... | 3.0 | ACT5DY536GISV | 07 27, 2009 | colour received blue shown yellowcouldnt chang... | 64 | gotten, many, strong, shown, compliment, surpr... |
| 1 | B0000V9K32 | Very cute and is really practical. Fits better... | 5.0 | A3BVWMS9I8OH8U | 12 26, 2009 | cute really practical fit better smaller wrist... | 19 | room, sister, backpack, school, penny, flexibl... |
| 2 | B0000V9K3W | The watch was exactly what i ordered and I got... | 4.0 | A5RZS69KSJH00 | 10 24, 2009 | watch exactly ordered got fast unfortunately b... | 59 | ask, refund, xmas, sent, attention, get, received |
| 3 | B0000V9K46 | This product came promptly and as described, p... | 5.0 | A3F8O512N9UNVM | 03 26, 2008 | came promptly described pleasure business themd | 17 | advertised, rating, cold, chose, promptly, wea... |
| 4 | B0000V9KNM | Why isn't Nike making these anymore? I love t... | 4.0 | A2EAKTCKFRF7A4 | 11 16, 2011 | isnt making anymore love watch get lot complim... | 74 | pant, fit, smooth, great, love, ride, good |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 21565 | B00KRENKNS | love it | 5.0 | AQOZEPFW4HTAR | 07 15, 2014 | love | 67 | love, fit, exactly, perfect, great, comfortabl... |
| 21566 | B00KXBJQ1A | They fit perfect and the are really light | 5.0 | A3H37LNK1EFP7C | 07 21, 2014 | fit perfect really light | 67 | love, fit, exactly, perfect, great, comfortabl... |
| 21567 | B00L01ML5K | The product was shipped in record speed! I lov... | 5.0 | A1N0CN53K1G2RW | 07 6, 2014 | shipped record speed love sneaker look feel aw... | 60 | size, small, half, bigger, larger, fit, order |
| 21568 | B00L2ADWCA | I like this item but they didn't have my size ... | 5.0 | AP318RPSIQQFA | 07 1, 2014 | like item didnt size tild alert | 70 | delivered, family, durability, waterproof, per... |
| 21569 | B00L5K86LO | Love it ! | 5.0 | A1KBC812A7RSY9 | 07 20, 2014 | love | 67 | love, fit, exactly, perfect, great, comfortabl... |
21570 rows × 8 columns
# ==========================
# 9. INSIGHTS
# ==========================
# Example: Most common ASINs per topic
topic_summary = reviews_df.groupby('topic')['asin'].value_counts().groupby(level=0).head(3)
# Convert to DataFrame and give count column a proper name
result = topic_summary.sort_values(ascending=False).head(25).reset_index(name='count')
# Set pandas display options to show full text
pd.set_option('display.max_colwidth', None)
pd.set_option('display.width', None)
pd.set_option('display.max_columns', None)
# Display the result
result
| topic | asin | count | |
|---|---|---|---|
| 0 | 48 | B00515GDJG | 89 |
| 1 | 48 | B00515GEJK | 61 |
| 2 | 60 | B000V4YZ1K | 46 |
| 3 | 60 | B003HD6KY2 | 38 |
| 4 | 27 | B004IM1GHW | 35 |
| 5 | 60 | B0098G7Q1S | 32 |
| 6 | 48 | B004YI0X6A | 31 |
| 7 | 73 | B003NYUSPM | 27 |
| 8 | 14 | B004IM1GHW | 26 |
| 9 | 27 | B007FXKMLW | 21 |
| 10 | 47 | B004IM1GHW | 20 |
| 11 | 46 | B000V4YZ1K | 18 |
| 12 | 36 | B0036DRWKO | 18 |
| 13 | 73 | B000V4YZ1K | 18 |
| 14 | 26 | B002JB6VEC | 17 |
| 15 | 67 | B000V4YZ1K | 15 |
| 16 | 68 | B003NYUSPM | 14 |
| 17 | 67 | B006RBH2PW | 13 |
| 18 | 65 | B007FXKMLW | 13 |
| 19 | 33 | B004IM1GHW | 13 |
| 20 | 37 | B007FXKMLW | 13 |
| 21 | 7 | B007FXKMLW | 13 |
| 22 | 33 | B007FXKMLW | 12 |
| 23 | 67 | B000G42Z2Q | 12 |
| 24 | 49 | B003NYUSPM | 12 |
# ==========================
# 9. INSIGHTS
# ==========================
# Top ASIN (most reviewed product) for each topic
topic_summary = reviews_df.groupby('topic')['asin'].value_counts().groupby(level=0).head(1)
# Convert to DataFrame and give count column a proper name
result = topic_summary.reset_index(name='review_count')
# Set pandas display options to show full text
pd.set_option('display.max_colwidth', None)
pd.set_option('display.width', None)
pd.set_option('display.max_columns', None)
# Display the result
result
| topic | asin | review_count | |
|---|---|---|---|
| 0 | 0 | B00AMTMRQE | 2 |
| 1 | 1 | B000V4YZ1K | 11 |
| 2 | 2 | B007FXKMLW | 6 |
| 3 | 3 | B0098G7Q1S | 4 |
| 4 | 4 | B007FXKMLW | 5 |
| ... | ... | ... | ... |
| 70 | 70 | B000V4YZ1K | 4 |
| 71 | 71 | B001LDDR0K | 6 |
| 72 | 72 | B005OBFUU0 | 2 |
| 73 | 73 | B003NYUSPM | 27 |
| 74 | 74 | B003NYUSPM | 4 |
75 rows × 3 columns
# ==========================
# INTERACTIVE PLOT WITH TOOLTIPS
# ==========================
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
# Get the top ASIN for each topic
topic_summary = reviews_df.groupby('topic')['asin'].value_counts().groupby(level=0).head(1)
result = topic_summary.reset_index(name='review_count')
# Get sample review text for each top ASIN to show in tooltip
def get_sample_reviews(topic, asin, n_samples=3):
sample_reviews = reviews_df[
(reviews_df['topic'] == topic) &
(reviews_df['asin'] == asin)
]['reviewText'].head(n_samples).tolist()
# Truncate long reviews and join with line breaks
truncated_reviews = []
for review in sample_reviews:
if len(str(review)) > 150:
truncated_reviews.append(str(review)[:150] + "...")
else:
truncated_reviews.append(str(review))
return "<br><br>".join(truncated_reviews)
# Add sample review texts to the result dataframe
result['sample_reviews'] = result.apply(
lambda row: get_sample_reviews(row['topic'], row['asin']), axis=1
)
# Create interactive bar plot
fig = px.bar(
result,
x='topic',
y='review_count',
title='Top Product (ASIN) by Review Count per Topic',
labels={'review_count': 'Number of Reviews', 'topic': 'Topic'},
color='review_count',
color_continuous_scale='viridis'
)
# Update traces to include custom hover template
fig.update_traces(
hovertemplate="<b>Topic:</b> %{x}<br>" +
"<b>ASIN:</b> %{customdata[0]}<br>" +
"<b>Review Count:</b> %{y}<br><br>" +
"<b>Sample Reviews:</b><br>%{customdata[1]}" +
"<extra></extra>",
customdata=list(zip(result['asin'], result['sample_reviews']))
)
# Customize layout
fig.update_layout(
xaxis_tickangle=-45,
height=600,
width=1000,
showlegend=False,
hovermode='closest'
)
# Show the plot
fig.show()
# ==========================
# INTERACTIVE PLOT WITH TOP 2 PRODUCTS AND TOOLTIPS
# ==========================
import plotly.express as px
import pandas as pd
# Get the top 2 ASINs for each topic
topic_summary = (
reviews_df.groupby('topic')['asin']
.value_counts()
.groupby(level=0)
.head(3) # top 2 products per topic
.reset_index(name='review_count')
)
# Function to get sample reviews for a given topic and ASIN
def get_sample_reviews(topic, asin, n_samples=3):
sample_reviews = reviews_df[
(reviews_df['topic'] == topic) &
(reviews_df['asin'] == asin)
]['reviewText'].head(n_samples).tolist()
truncated_reviews = []
for review in sample_reviews:
if len(str(review)) > 150:
truncated_reviews.append(str(review)[:150] + "...")
else:
truncated_reviews.append(str(review))
return "<br><br>".join(truncated_reviews)
# Add sample review texts to the dataframe
topic_summary['sample_reviews'] = topic_summary.apply(
lambda row: get_sample_reviews(row['topic'], row['asin']), axis=1
)
# Create a combined tooltip string for each topic showing both top products
tooltip_data = []
for topic in topic_summary['topic'].unique():
subset = topic_summary[topic_summary['topic'] == topic]
hover_text = ""
for idx, row in subset.iterrows():
hover_text += f"<b>Topic:</b> {row['topic']}<br>"
hover_text += f"<b>ASIN:</b> {row['asin']}<br>"
hover_text += f"<b>Review Count:</b> {row['review_count']}<br>"
hover_text += f"<b>Sample Reviews:</b><br>{row['sample_reviews']}<br><br>"
tooltip_data.append((topic, hover_text.strip()))
# Prepare dataframe for plotting: one bar per topic (sum of top 2 review counts)
plot_df = topic_summary.groupby('topic')['review_count'].sum().reset_index()
plot_df['hover_text'] = plot_df['topic'].map(dict(tooltip_data))
# Create interactive bar plot
fig = px.bar(
plot_df,
x='topic',
y='review_count',
title='Top 3 Products by Review Count per Topic',
labels={'review_count': 'Sum of Top 3 Reviews', 'topic': 'Topic'},
color='review_count',
color_continuous_scale='viridis'
)
# Update hover template
fig.update_traces(
hovertemplate="%{customdata}<extra></extra>",
customdata=plot_df['hover_text']
)
# Customize layout
fig.update_layout(
xaxis_tickangle=-45,
height=600,
width=1000,
showlegend=False,
hovermode='closest'
)
fig.show()
import pandas as pd
import plotly.express as px
# Example: Aggregate topic counts and average rating
topic_summary = (
reviews_df.groupby('topic')
.agg(
count=('topic', 'size'),
avg_rating=('overall', 'mean'),
topic_top_words=('topic_top_words', 'first')
)
.reset_index()
)
# Plot distribution with tooltips
fig = px.bar(
topic_summary,
x='topic',
y='count',
text='count',
hover_data={'avg_rating': ':.2f', 'topic': True, 'count': True, 'topic_top_words':True},
labels={'topic': 'Topic', 'count': 'Number of Reviews'},
title='Distribution of 75 Topics in Reviews with Average Rating'
)
fig.update_traces(marker_color='steelblue')
fig.update_layout(xaxis=dict(tickmode='linear'))
fig.show()
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Sort top and bottom 5 topics
top5 = topic_summary.sort_values(by="count", ascending=False).head(5)
bot5 = topic_summary.sort_values(by="count", ascending=True).head(5)
# Create subplot figure with 1 row, 2 columns
fig = make_subplots(rows=1, cols=2, specs=[[{'type':'domain'}, {'type':'domain'}]],
subplot_titles=('Top 5 Topics', 'Bottom 5 Topics'))
# Add top 5 pie
fig.add_trace(
go.Pie(
labels=top5['topic'],
values=top5['count'],
hovertext=top5['topic_top_words'],
hoverinfo='label+value+text'
),
row=1, col=1
)
# Add bottom 5 pie
fig.add_trace(
go.Pie(
labels=bot5['topic'],
values=bot5['count'],
hovertext=bot5['topic_top_words'],
hoverinfo='label+value+text'
),
row=1, col=2
)
# Update layout
fig.update_layout(title_text='Top and Bottom 5 Topics by Count in Reviews')
fig.show()
import pandas as pd
from nltk.sentiment import SentimentIntensityAnalyzer
import matplotlib.pyplot as plt
import seaborn as sns
# Make sure NLTK vader lexicon is downloaded
import nltk
nltk.download('vader_lexicon')
sia = SentimentIntensityAnalyzer()
# Compute sentiment score for each review
reviews_df['sentiment'] = reviews_df['reviewText'].apply(lambda x: sia.polarity_scores(x)['compound'])
[nltk_data] Downloading package vader_lexicon to [nltk_data] C:\Users\forca\AppData\Roaming\nltk_data... [nltk_data] Package vader_lexicon is already up-to-date!
# Aggregate both average sentiment and overall rating per topic
topic_summary = reviews_df.groupby('topic').agg(
avg_sentiment=('sentiment', 'mean'),
avg_overall=('overall', 'mean'),
count=('reviewText', 'count')
).reset_index()
# Interactive bar plot
fig = px.bar(
topic_summary,
x='topic',
y='avg_sentiment',
color='avg_sentiment', # diverging color map
color_continuous_scale='RdBu_r', # red=positive, blue=negative
hover_data={
'avg_sentiment': ':.2f',
'avg_overall': ':.2f',
'count': True
},
labels={'avg_sentiment': 'Avg Sentiment', 'topic': 'Topic'},
title='Average Sentiment per Topic with Avg Overall Rating'
)
fig.update_layout(xaxis_tickangle=-45)
fig.show()
# ==========================
# ADVANCED ANALYSIS IDEAS
# ==========================
# 1. SEGMENTATION BY STAR RATINGS (Easy)
# =====================================
print("1. Analysis by Star Ratings")
print("="*40)
# Separate positive vs negative reviews
positive_reviews = reviews_df[reviews_df['overall'] >= 4]
negative_reviews = reviews_df[reviews_df['overall'] <= 2]
neutral_reviews = reviews_df[reviews_df['overall'] == 3]
# Compare topic distributions
positive_topics = positive_reviews['topic'].value_counts().head(5)
negative_topics = negative_reviews['topic'].value_counts().head(5)
print("Top topics in positive reviews:")
print(positive_topics)
print("\nTop topics in negative reviews:")
print(negative_topics)
# Visualize the comparison
import matplotlib.pyplot as plt
import seaborn as sns
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
positive_topics.plot(kind='barh', ax=ax1, title='Top Topics - Positive Reviews (4-5 stars)')
negative_topics.plot(kind='barh', ax=ax2, title='Top Topics - Negative Reviews (1-2 stars)')
plt.tight_layout()
plt.show()
1. Analysis by Star Ratings ======================================== Top topics in positive reviews: topic 60 1074 67 781 27 616 42 500 37 469 Name: count, dtype: int64 Top topics in negative reviews: topic 60 243 37 173 27 141 33 79 47 79 Name: count, dtype: int64
# ==========================================
# WORD FREQUENCIES PER TOPIC (POS vs NEG)
# ==========================================
from collections import Counter
import matplotlib.pyplot as plt
def get_top_words(df, topic_id, sentiment_label, n=20):
"""
df: reviews dataframe
topic_id: int, topic number
sentiment_label: 'positive' or 'negative'
n: top N words
"""
if sentiment_label == "negative":
subset = df[(df['topic'] == topic_id) & (df['overall'] <= 2)]
elif sentiment_label == "positive":
subset = df[(df['topic'] == topic_id) & (df['overall'] >= 4)]
else:
raise ValueError("sentiment_label must be 'positive' or 'negative'")
# Flatten all tokens from 'cleaned' (assumes it's tokenized list or space-separated string)
words = []
for text in subset['cleaned']:
if isinstance(text, str):
words.extend(text.split())
elif isinstance(text, list):
words.extend(text)
return Counter(words).most_common(n)
# Define target topics
negative_topics_list = [53, 63, 51, 19, 14]
positive_topics_list = [63, 14, 70, 19, 64]
# Collect results
topic_word_stats = {}
for t in negative_topics_list:
topic_word_stats[(t, 'negative')] = get_top_words(reviews_df, t, 'negative', n=20)
for t in positive_topics_list:
topic_word_stats[(t, 'positive')] = get_top_words(reviews_df, t, 'positive', n=20)
# ========== DISPLAY RESULTS (commented out the print) ==========
#for (topic_id, sentiment), words in topic_word_stats.items():
# print(f"\nTop words for topic {topic_id} ({sentiment} reviews):")
# for word, count in words:
# print(f"{word}: {count}")
fig, axes = plt.subplots(2, 5, figsize=(25, 10))
axes = axes.flatten()
for idx, ((topic_id, sentiment), words) in enumerate(topic_word_stats.items()):
labels, values = zip(*words) if words else ([], [])
axes[idx].barh(labels, values)
axes[idx].set_title(f"Topic {topic_id} ({sentiment})")
axes[idx].invert_yaxis()
plt.tight_layout()
plt.show()
# Define target topics
negative_topics_list = [63, 64, 14, 0, 25]
positive_topics_list = [63, 64, 14, 0, 25]
# Collect results
topic_word_stats = {}
for t in negative_topics_list:
topic_word_stats[(t, 'negative')] = get_top_words(reviews_df, t, 'negative', n=20)
for t in positive_topics_list:
topic_word_stats[(t, 'positive')] = get_top_words(reviews_df, t, 'positive', n=20)
# ========== DISPLAY RESULTS (commented out the print) ==========
#for (topic_id, sentiment), words in topic_word_stats.items():
# print(f"\nTop words for topic {topic_id} ({sentiment} reviews):")
# for word, count in words:
# print(f"{word}: {count}")
fig, axes = plt.subplots(2, 5, figsize=(25, 10))
axes = axes.flatten()
for idx, ((topic_id, sentiment), words) in enumerate(topic_word_stats.items()):
labels, values = zip(*words) if words else ([], [])
axes[idx].barh(labels, values)
axes[idx].set_title(f"Topic {topic_id} ({sentiment})")
axes[idx].invert_yaxis()
plt.tight_layout()
plt.show()
import plotly.graph_objs as go
from plotly.subplots import make_subplots
# topic_word_stats: dict keyed by (topic_id, sentiment) -> [(word, count), ...]
pairs = list(topic_word_stats.items()) # preserves ordering
rows, cols = 5, 2 # 5 rows x 2 cols = 10 slots
# Titles for each subplot
titles = [f"Topic {tid} ({sent})" for (tid, sent), _ in pairs]
fig = make_subplots(
rows=rows, cols=cols,
subplot_titles=titles,
horizontal_spacing=0.15,
vertical_spacing=0.1
)
# Add the 10 plots into the grid (row-major order)
for idx, ((topic_id, sentiment), words) in enumerate(pairs):
row = idx // cols + 1
col = idx % cols + 1
if words:
labels, values = zip(*words)
labels, values = list(labels), list(values)
else:
labels, values = [], []
fig.add_trace(
go.Bar(
x=values,
y=labels,
orientation='h',
hovertemplate="Word: %{y}<br>Count: %{x}<extra></extra>"
),
row=row, col=col
)
# Invert y-axis (like matplotlib barh)
fig.update_yaxes(
autorange="reversed",
automargin=True,
tickfont=dict(size=10),
row=row, col=col
)
fig.update_xaxes(automargin=True, row=row, col=col)
# Layout tweaks
fig.update_layout(
height=1800,
width=1200,
title_text="Top Words by Topic (Positive vs Negative) — 2 cols × 5 rows",
showlegend=False,
margin=dict(l=100, r=60, t=100, b=60)
)
fig.show()
import plotly.graph_objs as go
from plotly.subplots import make_subplots
import random
print("positive is 4+ stars, negative is 2- stars.")
# -------------------------------
# Define topic groups
# -------------------------------
negative_topic_ids = [53, 63, 51, 19, 14]
positive_topic_ids = [63, 14, 70, 19, 64]
# -------------------------------
# Build filtered ASIN counts and truncated sample reviews
# -------------------------------
all_topic_asins = {}
def get_top_asins_with_reviews(subset, n_asins=5, n_reviews=3, max_len=150):
top_asins = subset['asin'].value_counts().head(n_asins)
hover_texts = []
for asin in top_asins.index:
reviews = subset[subset['asin'] == asin]['reviewText'].dropna().tolist()
sample_reviews = random.sample(reviews, min(len(reviews), n_reviews))
# Truncate long reviews
truncated_reviews = []
for review in sample_reviews:
review_str = str(review)
if len(review_str) > max_len:
truncated_reviews.append(review_str[:max_len] + "...")
else:
truncated_reviews.append(review_str)
hover_text = "<br>".join(truncated_reviews)
hover_texts.append(hover_text)
return top_asins, hover_texts
# Negative topics
for t in negative_topic_ids:
subset = reviews_df[(reviews_df['topic'] == t) & (reviews_df['overall'] <= 2)]
top_asins, hover_texts = get_top_asins_with_reviews(subset)
all_topic_asins[(t, 'Negative')] = (top_asins, hover_texts)
# Positive topics
for t in positive_topic_ids:
subset = reviews_df[(reviews_df['topic'] == t) & (reviews_df['overall'] >= 4)]
top_asins, hover_texts = get_top_asins_with_reviews(subset)
all_topic_asins[(t, 'Positive')] = (top_asins, hover_texts)
# -------------------------------
# Prepare subplot layout
# -------------------------------
pairs = list(all_topic_asins.items())
rows, cols = 5, 2 # 10 topics -> 2 cols x 5 rows
titles = [f"Topic {tid} ({sentiment})" for (tid, sentiment), _ in pairs]
fig = make_subplots(
rows=rows, cols=cols,
subplot_titles=titles,
horizontal_spacing=0.15,
vertical_spacing=0.1
)
# -------------------------------
# Add ASIN bar charts with truncated sample reviews in hover
# -------------------------------
for idx, ((topic_id, sentiment), (asin_counts, hover_texts)) in enumerate(pairs):
row = idx // cols + 1
col = idx % cols + 1
labels = asin_counts.index.tolist()
values = asin_counts.values.tolist()
fig.add_trace(
go.Bar(
x=values,
y=labels,
orientation='h',
hovertemplate=[
f"ASIN: {asin}<br>Count: {count}<br><br>Sample Reviews:<br>{hover}"
for asin, count, hover in zip(labels, values, hover_texts)
]
),
row=row, col=col
)
fig.update_yaxes(autorange="reversed", automargin=True, tickfont=dict(size=10), row=row, col=col)
fig.update_xaxes(automargin=True, row=row, col=col)
# -------------------------------
# Layout tweaks
# -------------------------------
fig.update_layout(
height=1800,
width=1200,
title_text="Top 5 ASINs per Topic (Filtered by Negative/Positive Reviews) with Truncated Sample Reviews",
showlegend=False,
margin=dict(l=100, r=60, t=100, b=60)
)
fig.show()
positive is 4+ stars, negative is 2- stars.
import random
import plotly.graph_objects as go
from plotly.subplots import make_subplots
print("positive is 4+ stars, negative is 2- stars.")
# -------------------------------
# Define topic groups
# -------------------------------
topic_ids = [63, 64, 14, 0, 25]
# -------------------------------
# Function to get top ASINs and sample reviews
# -------------------------------
def get_top_asins_with_reviews(subset, n_asins=5, n_reviews=3, max_len=150):
top_asins = subset['asin'].value_counts().head(n_asins)
hover_texts = []
for asin in top_asins.index:
reviews = subset[subset['asin'] == asin]['reviewText'].dropna().tolist()
if not reviews:
hover_texts.append("No reviews available")
continue
sample_reviews = random.sample(reviews, min(len(reviews), n_reviews))
truncated_reviews = []
for review in sample_reviews:
review_str = str(review)
if len(review_str) > max_len:
truncated_reviews.append(review_str[:max_len] + "...")
else:
truncated_reviews.append(review_str)
hover_text = "<br>".join(truncated_reviews)
hover_texts.append(hover_text)
return top_asins, hover_texts
# -------------------------------
# Collect data for each topic/sentiment
# -------------------------------
all_topic_asins = {}
for t in topic_ids:
# Negative reviews
subset_neg = reviews_df[(reviews_df['topic'] == t) & (reviews_df['overall'] <= 2)]
top_asins_neg, hover_neg = get_top_asins_with_reviews(subset_neg)
all_topic_asins[(t, 'Negative')] = (top_asins_neg, hover_neg)
# Positive reviews
subset_pos = reviews_df[(reviews_df['topic'] == t) & (reviews_df['overall'] >= 4)]
top_asins_pos, hover_pos = get_top_asins_with_reviews(subset_pos)
all_topic_asins[(t, 'Positive')] = (top_asins_pos, hover_pos)
# -------------------------------
# Prepare subplot layout
# -------------------------------
rows = len(topic_ids)
cols = 2 # Negative | Positive
titles = []
for t in topic_ids:
titles.extend([f"Topic {t} (Negative)", f"Topic {t} (Positive)"])
fig = make_subplots(
rows=rows, cols=cols,
subplot_titles=titles,
horizontal_spacing=0.15,
vertical_spacing=0.15
)
# -------------------------------
# Add ASIN bar charts
# -------------------------------
for row_idx, t in enumerate(topic_ids, start=1):
for col_idx, sentiment in enumerate(['Negative', 'Positive'], start=1):
asin_counts, hover_texts = all_topic_asins[(t, sentiment)]
labels = asin_counts.index.tolist()
values = asin_counts.values.tolist()
fig.add_trace(
go.Bar(
x=values,
y=labels,
orientation='h',
hovertemplate=[
f"ASIN: {asin}<br>Count: {count}<br><br>Sample Reviews:<br>{hover}"
for asin, count, hover in zip(labels, values, hover_texts)
]
),
row=row_idx, col=col_idx
)
fig.update_yaxes(autorange="reversed", automargin=True, tickfont=dict(size=10), row=row_idx, col=col_idx)
fig.update_xaxes(automargin=True, row=row_idx, col=col_idx)
# -------------------------------
# Layout tweaks
# -------------------------------
fig.update_layout(
height=1800,
width=1200,
title_text="Top 5 ASINs per Topic (Negative vs Positive) with Sample Reviews",
showlegend=False,
margin=dict(l=100, r=60, t=100, b=60)
)
fig.show()
positive is 4+ stars, negative is 2- stars.
# 3. TEMPORAL ANALYSIS
# ==================================
print("\n3. Temporal Analysis")
print("="*40)
# Convert reviewTime to datetime if not already
reviews_df['reviewTime'] = pd.to_datetime(reviews_df['reviewTime'])
reviews_df['year'] = reviews_df['reviewTime'].dt.year
reviews_df['month'] = reviews_df['reviewTime'].dt.month
# Seasonal analysis
seasonal_topics = reviews_df.groupby(['month', 'topic']).size().unstack(fill_value=0)
print("\nTopic trends by month (seasonality):")
print(seasonal_topics.head(12))
3. Temporal Analysis ======================================== Topic trends by month (seasonality): topic 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 \ month 1 4 30 16 22 34 34 28 59 12 35 21 15 23 26 39 30 16 8 2 5 19 23 21 15 18 25 26 14 38 18 11 24 39 40 36 9 8 3 8 38 22 22 35 25 38 46 18 36 14 14 17 33 40 31 17 12 4 3 24 38 22 28 36 24 53 31 16 19 22 21 47 52 40 22 13 5 8 41 22 24 30 36 24 38 24 5 11 17 18 42 50 29 15 11 6 12 32 32 23 27 28 29 42 33 12 15 15 13 34 43 42 18 7 7 29 24 27 21 25 21 23 46 15 23 18 9 40 36 49 45 8 13 8 3 12 14 9 20 16 13 15 11 5 8 7 8 18 23 11 8 3 9 2 15 10 15 15 14 14 21 7 7 7 4 5 32 26 15 5 4 10 1 14 15 13 13 16 15 17 8 11 11 5 8 19 30 20 9 5 11 1 19 16 12 22 12 18 16 7 17 6 7 10 27 19 10 10 4 12 5 34 12 24 20 27 23 34 13 43 23 7 21 30 35 27 14 13 topic 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 \ month 1 6 25 11 34 37 23 40 6 31 53 9 19 33 17 8 48 26 2 5 31 13 19 20 26 30 10 16 73 6 19 26 15 12 39 19 3 5 41 14 35 39 26 39 13 51 88 4 25 25 18 14 74 24 4 9 39 24 28 31 28 40 18 37 108 12 22 22 21 20 57 18 5 9 41 16 22 38 20 37 18 45 99 15 17 16 22 12 58 23 6 7 34 15 33 34 16 35 16 41 71 12 22 23 19 9 46 25 7 14 29 15 32 34 19 26 18 38 74 8 25 21 15 11 54 17 8 3 16 4 15 12 14 14 4 23 60 2 3 15 13 8 28 14 9 1 14 12 13 29 8 15 7 14 60 5 18 9 12 4 30 13 10 3 17 6 23 16 6 17 4 18 50 5 9 15 12 4 13 11 11 5 17 7 17 16 10 22 3 18 43 6 9 13 12 5 32 15 12 7 32 15 21 29 24 25 10 29 72 11 18 36 10 11 45 16 topic 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 \ month 1 35 36 81 19 17 11 25 45 21 25 19 23 20 55 29 17 31 9 2 35 29 63 20 8 8 31 38 21 15 15 22 26 58 30 17 35 8 3 43 26 75 31 23 12 25 62 20 19 21 35 39 64 28 28 45 16 4 35 33 73 34 24 16 46 55 22 24 19 37 27 57 40 17 44 26 5 36 28 53 39 20 16 35 64 20 18 21 37 42 45 33 11 35 12 6 49 27 64 26 13 8 40 57 19 15 16 39 46 43 29 19 37 13 7 44 32 66 31 20 15 30 74 18 18 18 25 34 46 43 11 35 15 8 21 15 51 19 10 5 18 18 14 10 11 18 22 29 21 10 15 9 9 20 13 51 20 12 6 25 18 8 7 10 20 15 29 14 7 21 6 10 16 16 47 17 8 4 17 26 5 12 11 17 21 22 20 10 20 4 11 16 10 53 15 7 5 14 32 13 12 8 24 20 19 13 13 18 4 12 32 32 51 25 20 9 25 33 19 15 19 26 22 42 37 15 31 5 topic 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 \ month 1 6 12 25 45 15 21 20 148 19 16 13 28 42 12 57 21 7 2 11 13 20 31 11 15 23 111 17 13 11 21 37 9 47 25 12 3 9 12 20 33 30 16 22 190 20 25 10 21 40 20 93 38 22 4 7 10 13 34 16 25 33 157 23 19 13 22 41 10 67 53 14 5 8 13 13 45 16 17 27 172 23 21 8 35 25 16 56 31 19 6 8 12 16 37 21 16 18 213 28 26 15 37 32 27 92 31 20 7 6 9 13 19 24 18 22 162 30 26 15 30 33 46 197 30 18 8 7 9 11 26 11 10 16 56 9 10 6 12 12 7 29 14 11 9 3 8 12 30 10 12 11 97 13 10 5 17 23 7 35 22 12 10 8 6 6 27 5 7 14 88 13 11 8 6 33 5 30 17 10 11 4 9 16 26 11 10 8 61 10 12 8 14 39 7 42 17 7 12 6 14 32 30 13 21 29 116 28 25 8 29 24 15 62 30 11 topic 70 71 72 73 74 month 1 25 25 2 38 24 2 15 26 4 32 18 3 27 31 7 30 29 4 34 33 2 29 35 5 11 22 3 27 39 6 18 19 4 31 41 7 17 22 4 31 23 8 14 12 7 14 11 9 8 13 0 20 14 10 11 9 1 15 13 11 13 17 0 23 13 12 24 32 2 38 16
import numpy as np
import pandas as pd
# Ensure reviewTime is datetime
reviews_df['reviewTime'] = pd.to_datetime(reviews_df['reviewTime'])
reviews_df['month'] = reviews_df['reviewTime'].dt.month
# Count reviews per month per topic
seasonal_topics = reviews_df.groupby(['month', 'topic']).size().unstack(fill_value=0)
# Log-transform counts (add 1 to avoid log(0))
log_counts = np.log1p(seasonal_topics)
# Mean across topics for each month
month_popularity = log_counts.sum(axis=1)
# Display
print("Log-transformed summed review counts per month:")
print(month_popularity)
Log-transformed summed review counts per month: month 1 234.608708 2 226.930932 3 246.091147 4 247.316282 5 240.029166 6 242.125116 7 242.570914 8 192.285163 9 191.662491 10 189.558463 11 193.861213 12 231.726066 dtype: float64
import plotly.graph_objs as go
# month_popularity from last snippet (total reviews per month)
fig = go.Figure(
data=go.Bar(
x=month_popularity.index,
y=month_popularity.values,
text=month_popularity.values, # show raw counts on hover
textposition='auto',
marker_color='teal',
hovertemplate="Month: %{x}<br>Total Reviews: %{y}<extra></extra>"
)
)
fig.update_layout(
title="Total Reviews per Month Across All Topics (log transformed)",
xaxis_title="Month",
yaxis_title="Total Reviews",
xaxis=dict(tickmode='linear'),
yaxis=dict(range=[150, 250]), # zoomed range
template='plotly_white',
height=500
)
fig.show()
# 4. SENTIMENT ANALYSIS ENHANCEMENT
# ===============================================
print("\n4. Enhanced Sentiment Analysis")
print("="*40)
from textblob import TextBlob
# Add sentiment scores
def get_sentiment(text):
return TextBlob(str(text)).sentiment.polarity
reviews_df['sentiment_score'] = reviews_df['reviewText'].apply(get_sentiment)
reviews_df['sentiment_category'] = pd.cut(
reviews_df['sentiment_score'],
bins=[-1, -0.1, 0.1, 1],
labels=['Negative', 'Neutral', 'Positive']
)
# Analyze topics by sentiment
sentiment_topics = reviews_df.groupby(['sentiment_category', 'topic']).size().unstack(fill_value=0)
print("Topics by sentiment category:")
print(sentiment_topics)
4. Enhanced Sentiment Analysis ======================================== Topics by sentiment category: topic 0 1 2 3 4 5 6 7 8 9 10 11 \ sentiment_category Negative 3 18 4 14 11 10 13 11 8 3 8 26 Neutral 34 42 28 22 41 34 50 58 37 201 23 29 Positive 44 242 215 192 231 239 211 343 148 44 140 78 topic 12 13 14 15 16 17 18 19 20 21 22 23 \ sentiment_category Negative 4 16 29 13 8 5 3 7 1 6 11 5 Neutral 25 72 70 43 22 14 18 42 12 25 42 17 Positive 179 295 347 279 121 82 53 287 139 261 282 198 topic 24 25 26 27 28 29 30 31 32 33 34 35 \ sentiment_category Negative 9 13 17 35 7 12 14 10 2 31 10 9 Neutral 53 18 38 222 17 35 45 33 18 85 29 28 Positive 278 96 306 594 71 159 195 143 98 408 182 345 topic 36 37 38 39 40 41 42 43 44 45 46 47 \ sentiment_category Negative 6 41 11 17 5 15 5 18 18 3 18 25 Neutral 20 187 64 29 27 62 30 43 43 23 70 86 Positive 271 500 221 136 83 254 487 139 129 162 235 223 topic 48 49 50 51 52 53 54 55 56 57 58 59 \ sentiment_category Negative 5 11 4 11 11 3 2 3 20 8 15 33 Neutral 79 32 24 38 17 23 12 17 70 23 37 61 Positive 425 294 147 318 99 57 113 177 293 152 134 148 topic 60 61 62 63 64 65 66 67 68 69 70 71 \ sentiment_category Negative 120 10 4 6 9 10 10 6 15 16 13 14 Neutral 487 41 17 17 29 78 17 41 66 40 27 27 Positive 964 182 193 97 234 293 154 760 248 107 177 220 topic 72 73 74 sentiment_category Negative 0 10 6 Neutral 6 48 33 Positive 30 270 237
# 4b. TOP NEGATIVELY PERCEIVED TOPICS BY NEG/POS RATIO
# =====================================================
print("\nTop Negatively Perceived Topics (by Negative/Positive Ratio)")
print("="*60)
# Aggregate counts of each sentiment per topic (if not already)
sentiment_topics = reviews_df.groupby(['topic', 'sentiment_category']).size().unstack(fill_value=0)
# Compute Negative/Positive ratio
sentiment_topics['neg_pos_ratio'] = sentiment_topics.apply(
lambda row: row['Negative'] / row['Positive'] if row['Positive'] > 0 else float('inf'),
axis=1
)
# Sort topics by negative-to-positive ratio
top_negative_topics = sentiment_topics.sort_values('neg_pos_ratio', ascending=False)
# Display top 10 most negatively perceived topics
print(top_negative_topics[['Negative', 'Positive', 'Neutral', 'neg_pos_ratio']].head(10))
Top Negatively Perceived Topics (by Negative/Positive Ratio) ============================================================ sentiment_category Negative Positive Neutral neg_pos_ratio topic 11 26 78 29 0.333333 59 33 148 61 0.222973 69 16 107 40 0.149533 44 18 129 43 0.139535 25 13 96 18 0.135417 43 18 139 43 0.129496 39 17 136 29 0.125000 60 120 964 487 0.124481 47 25 223 86 0.112108 58 15 134 37 0.111940
# 5. PRICE SENSITIVITY ANALYSIS (Intermediate)
# ============================================
print("\n5. Price Sensitivity Analysis")
print("="*40)
# Look for price-related keywords in reviews
price_keywords = ['price', 'expensive', 'cheap', 'value', 'worth', 'cost', 'deal', 'money']
price_mentions = reviews_df[reviews_df['reviewText'].str.contains('|'.join(price_keywords), case=False, na=False)]
print(f"Reviews mentioning price: {len(price_mentions)} out of {len(reviews_df)} ({len(price_mentions)/len(reviews_df)*100:.1f}%)")
# Analyze topics in price-sensitive reviews
price_topics = price_mentions['topic'].value_counts().head(10)
print("\nTop topics in price-sensitive reviews:")
print(price_topics)
5. Price Sensitivity Analysis ======================================== Reviews mentioning price: 3662 out of 21570 (17.0%) Top topics in price-sensitive reviews: topic 37 175 27 175 33 175 60 153 67 115 14 95 48 82 47 80 35 78 13 75 Name: count, dtype: int64
# 6. PRODUCT LIFECYCLE ANALYSIS (Advanced)
# ========================================
print("\n6. Product Lifecycle Analysis")
print("="*40)
# Analyze how topics change for products over time since launch
product_lifecycle = reviews_df.groupby(['asin', 'year', 'topic']).size().reset_index(name='count')
# Find products with long review histories
products_with_history = reviews_df.groupby('asin')['year'].nunique()
long_history_products = products_with_history[products_with_history >= 3]
print(f"Products with 3+ years of reviews: {len(long_history_products)}")
print(long_history_products.sort_values(ascending=False).head(10))
6. Product Lifecycle Analysis ======================================== Products with 3+ years of reviews: 365 asin B000E8J5PY 7 B000A8BUEC 6 B000NOCJJS 6 B001V6PNRW 6 B000A8BU0Q 6 B0030NKIH4 5 B000E8F2TM 5 B000E8H01K 5 B000E8H0LA 5 B003QL2SQO 5 Name: year, dtype: int64
# 8. REVIEW DEPTH ANALYSIS (Intermediate)
# =======================================
print("\n8. Review Depth Analysis")
print("="*40)
# Analyze review length and its relationship to topics
reviews_df['review_length'] = reviews_df['reviewText'].str.len()
reviews_df['review_depth'] = pd.cut(
reviews_df['review_length'],
bins=[0, 100, 500, float('inf')],
labels=['Short', 'Medium', 'Long']
)
depth_topics = reviews_df.groupby(['review_depth', 'topic']).size().unstack(fill_value=0)
print("Topics by review depth:")
print(depth_topics.head())
8. Review Depth Analysis ======================================== Topics by review depth: topic 0 1 2 3 4 5 6 7 8 9 10 11 12 \ review_depth Short 40 12 15 15 9 15 17 40 17 22 25 12 41 Medium 41 273 217 208 243 260 238 353 172 222 146 115 163 Long 0 17 15 5 32 8 19 20 4 4 0 6 4 topic 13 14 15 16 17 18 19 20 21 22 23 24 25 \ review_depth Short 14 40 35 11 11 9 27 14 29 27 24 14 20 Medium 278 382 270 136 89 63 295 138 259 299 196 306 104 Long 91 24 31 4 1 2 14 0 4 9 0 20 3 topic 26 27 28 29 30 31 32 33 34 35 36 37 38 \ review_depth Short 23 12 10 17 17 10 11 17 14 36 35 22 15 Medium 318 499 79 183 227 171 103 426 193 342 259 510 260 Long 20 340 6 6 10 5 4 81 14 4 3 196 21 topic 39 40 41 42 43 44 45 46 47 48 49 50 51 \ review_depth Short 14 13 9 55 16 8 15 19 14 47 38 10 36 Medium 163 99 260 445 176 172 168 274 265 415 292 149 325 Long 5 3 62 22 8 10 5 30 55 47 7 16 6 topic 52 53 54 55 56 57 58 59 60 61 62 63 64 \ review_depth Short 10 10 11 17 9 23 10 16 129 15 25 21 11 Medium 113 73 111 179 302 158 170 203 1303 202 185 96 253 Long 4 0 5 1 72 2 8 24 139 16 4 3 8 topic 65 66 67 68 69 70 71 72 73 74 review_depth Short 23 46 215 11 12 12 10 1 21 12 Medium 298 127 588 266 146 193 240 33 291 249 Long 60 8 4 52 5 12 11 2 16 15
# 9. FEATURE IMPORTANCE ANALYSIS (Advanced)
# =========================================
print("\n9. Feature Importance Analysis")
print("="*40)
# Extract specific product features mentioned
feature_keywords = {
'comfort': ['comfort', 'comfortable', 'cozy'],
'durability': ['durable', 'lasting', 'sturdy', 'quality'],
'design': ['design', 'style', 'look', 'appearance'],
'fit': ['fit', 'size', 'sizing', 'tight', 'loose'],
'performance': ['performance', 'speed', 'grip', 'traction']
}
for feature, keywords in feature_keywords.items():
feature_reviews = reviews_df[reviews_df['reviewText'].str.contains('|'.join(keywords), case=False, na=False)]
feature_topics = feature_reviews['topic'].value_counts().head(5)
print(f"\nTop topics mentioning {feature}:")
print(feature_topics)
9. Feature Importance Analysis ======================================== Top topics mentioning comfort: topic 60 386 27 361 67 254 42 221 14 170 Name: count, dtype: int64 Top topics mentioning durability: topic 27 116 60 111 48 110 51 77 42 71 Name: count, dtype: int64 Top topics mentioning design: topic 60 388 27 291 37 249 67 216 42 187 Name: count, dtype: int64 Top topics mentioning fit: topic 60 1338 67 395 27 369 33 212 42 205 Name: count, dtype: int64 Top topics mentioning performance: topic 27 59 71 32 37 31 61 26 60 26 Name: count, dtype: int64
# 10. ACTIONABLE INSIGHTS GENERATOR
# ============================================
print("\n10. Actionable Insights Generator")
print("="*40)
from collections import Counter
import re
def get_top_words(text_series, n_words=10):
"""Extract top words from a series of text"""
# Combine all text and clean it
all_text = ' '.join(text_series.astype(str))
# Remove punctuation and convert to lowercase
words = re.findall(r'\b[a-zA-Z]{3,}\b', all_text.lower())
# Remove common stopwords
stopwords = {'the', 'and', 'for', 'are', 'but', 'not', 'you', 'all', 'can', 'had', 'her', 'was', 'one', 'our', 'out', 'day', 'get', 'has', 'him', 'his', 'how', 'man', 'new', 'now', 'old', 'see', 'two', 'way', 'who', 'boy', 'did', 'its', 'let', 'put', 'say', 'she', 'too', 'use', 'this', 'that', 'with', 'have', 'from', 'they', 'know', 'want', 'been', 'good', 'much', 'some', 'time', 'very', 'when', 'come', 'here', 'just', 'like', 'long', 'make', 'many', 'over', 'such', 'take', 'than', 'them', 'well', 'were', 'will'}
filtered_words = [word for word in words if word not in stopwords and len(word) > 3]
return Counter(filtered_words).most_common(n_words)
def generate_insights(topic_id):
"""Generate specific insights for a topic"""
topic_reviews = reviews_df[reviews_df['topic'] == topic_id]
insights = {
'topic_id': topic_id,
'total_reviews': len(topic_reviews),
'avg_rating': topic_reviews['overall'].mean(),
'sentiment_distribution': topic_reviews['sentiment_category'].value_counts() if 'sentiment_category' in reviews_df.columns else 'N/A',
'top_products': topic_reviews['asin'].value_counts().head(3),
'seasonal_pattern': topic_reviews['month'].value_counts().head(3) if 'month' in reviews_df.columns else 'N/A',
'top_words': get_top_words(topic_reviews['reviewText'], 15),
'sample_reviews': topic_reviews['reviewText'].head(3).tolist()
}
return insights
# Example: Generate insights for topics
top_topics = reviews_df['topic'].value_counts().head(30).index
for topic in top_topics:
insights = generate_insights(topic)
print(f"\nInsights for Topic {topic}:")
print(f"- Reviews: {insights['total_reviews']}")
print(f"- Avg Rating: {insights['avg_rating']:.2f}")
print(f"- Top Product: {insights['top_products'].index[0]} ({insights['top_products'].iloc[0]} reviews)")
print(f"- Top Words: {', '.join([f'{word}({count})' for word, count in insights['top_words'][:10]])}")
print(f"- Product Clues: {', '.join([word for word, count in insights['top_words'][:15] if any(keyword in word.lower() for keyword in ['shoe', 'boot', 'sneaker', 'shirt', 'jacket', 'watch', 'phone', 'case', 'bag', 'nike', 'adidas', 'apple', 'samsung'])])}")
10. Actionable Insights Generator ======================================== Insights for Topic 60: - Reviews: 1571 - Avg Rating: 3.86 - Top Product: B000V4YZ1K (46 reviews) - Top Words: size(1847), shoes(984), these(956), shoe(658), small(574), nike(428), wear(415), half(413), would(387), great(382) - Product Clues: shoes, shoe, nike Insights for Topic 27: - Reviews: 851 - Avg Rating: 3.98 - Top Product: B004IM1GHW (35 reviews) - Top Words: shoes(1235), these(1138), shoe(861), nike(609), feet(392), running(391), pair(390), comfortable(337), wear(317), great(313) - Product Clues: shoes, shoe, nike Insights for Topic 67: - Reviews: 807 - Avg Rating: 4.79 - Top Product: B000V4YZ1K (15 reviews) - Top Words: shoes(338), these(329), great(301), comfortable(245), love(219), perfect(161), exactly(158), shoe(126), color(124), what(121) - Product Clues: shoes, shoe Insights for Topic 37: - Reviews: 728 - Avg Rating: 3.70 - Top Product: B007FXKMLW (13 reviews) - Top Words: watch(1019), nike(335), these(263), great(251), shoes(209), band(208), would(196), only(195), battery(163), bought(153) - Product Clues: watch, nike, shoes, shoe Insights for Topic 33: - Reviews: 524 - Avg Rating: 4.17 - Top Product: B004IM1GHW (13 reviews) - Top Words: these(490), shoes(474), shoe(266), nike(187), great(178), comfortable(157), pair(155), feet(150), wear(127), running(107) - Product Clues: shoes, shoe, nike Insights for Topic 42: - Reviews: 522 - Avg Rating: 4.72 - Top Product: B0098SW6BG (8 reviews) - Top Words: these(372), shoes(324), comfortable(220), great(216), love(154), shoe(143), wear(106), size(106), nike(101), awesome(93) - Product Clues: shoes, shoe, nike Insights for Topic 48: - Reviews: 509 - Avg Rating: 4.51 - Top Product: B00515GDJG (89 reviews) - Top Words: great(175), shoes(162), perfect(120), size(120), clothes(101), love(90), these(89), would(87), carry(80), small(73) - Product Clues: shoes, nike, shoe Insights for Topic 14: - Reviews: 446 - Avg Rating: 4.23 - Top Product: B004IM1GHW (26 reviews) - Top Words: shoes(302), these(292), comfortable(174), shoe(158), pair(139), ever(128), nike(125), great(121), best(105), love(90) - Product Clues: shoes, shoe, nike Insights for Topic 7: - Reviews: 413 - Avg Rating: 4.56 - Top Product: B007FXKMLW (13 reviews) - Top Words: shoes(216), these(215), great(137), comfortable(91), pair(76), shoe(76), would(71), bought(69), nike(68), thank(64) - Product Clues: shoes, shoe, nike Insights for Topic 13: - Reviews: 383 - Avg Rating: 4.13 - Top Product: B0098G7Q1S (8 reviews) - Top Words: shoes(356), these(355), shoe(199), nike(152), great(139), comfortable(134), feet(130), running(114), pair(111), wear(93) - Product Clues: shoes, shoe, nike Insights for Topic 56: - Reviews: 383 - Avg Rating: 3.92 - Top Product: B000E8H01K (6 reviews) - Top Words: watch(403), these(164), nike(164), great(160), shoes(127), would(82), size(80), face(78), pair(78), shoe(74) - Product Clues: watch, nike, shoes, shoe Insights for Topic 35: - Reviews: 382 - Avg Rating: 4.62 - Top Product: B004IM1GHW (8 reviews) - Top Words: shoes(211), great(192), these(184), recommend(139), comfortable(135), shoe(120), would(107), anyone(83), love(77), nike(61) - Product Clues: shoes, shoe, nike Insights for Topic 65: - Reviews: 381 - Avg Rating: 4.12 - Top Product: B007FXKMLW (13 reviews) - Top Words: watch(415), great(136), these(118), nike(102), wrist(100), shoes(98), comfortable(97), easy(83), band(81), shoe(75) - Product Clues: watch, nike, shoes, shoe Insights for Topic 51: - Reviews: 367 - Avg Rating: 4.61 - Top Product: B000V4YZ1K (7 reviews) - Top Words: shoes(182), these(146), great(105), comfortable(86), nike(76), love(71), nice(70), quality(67), shoe(67), look(64) - Product Clues: shoes, nike, shoe Insights for Topic 26: - Reviews: 361 - Avg Rating: 4.54 - Top Product: B002JB6VEC (17 reviews) - Top Words: these(252), shoes(218), comfortable(163), shoe(121), pair(118), great(98), feet(95), work(90), nike(88), bought(74) - Product Clues: shoes, shoe, nike Insights for Topic 24: - Reviews: 340 - Avg Rating: 4.42 - Top Product: B001V6PNRW (8 reviews) - Top Words: shoes(218), these(196), great(101), shoe(91), comfortable(87), size(72), nike(67), love(64), would(54), pair(48) - Product Clues: shoes, shoe, nike Insights for Topic 49: - Reviews: 337 - Avg Rating: 4.61 - Top Product: B003NYUSPM (12 reviews) - Top Words: these(204), shoes(166), great(112), comfortable(108), shoe(95), excellent(81), socks(59), bought(54), nike(53), loves(48) - Product Clues: shoes, shoe, nike Insights for Topic 19: - Reviews: 336 - Avg Rating: 4.51 - Top Product: B007FXKMLW (5 reviews) - Top Words: shoes(186), these(172), shoe(107), great(91), comfortable(72), pair(67), love(65), nike(58), bought(48), size(46) - Product Clues: shoes, shoe, nike Insights for Topic 15: - Reviews: 336 - Avg Rating: 4.26 - Top Product: B007FXKMLW (8 reviews) - Top Words: shoes(280), these(256), shoe(170), great(118), comfortable(92), nike(86), running(85), support(85), pair(80), feet(79) - Product Clues: shoes, shoe, nike Insights for Topic 22: - Reviews: 335 - Avg Rating: 4.40 - Top Product: B0006NGUE6 (9 reviews) - Top Words: shoes(227), these(214), comfortable(146), great(117), shoe(107), golf(83), wear(75), love(70), look(69), size(58) - Product Clues: shoes, shoe, nike Insights for Topic 47: - Reviews: 334 - Avg Rating: 3.71 - Top Product: B004IM1GHW (20 reviews) - Top Words: shoes(258), these(252), shoe(169), nike(149), comfortable(114), size(86), great(86), pair(81), wear(69), more(60) - Product Clues: shoes, shoe, nike Insights for Topic 41: - Reviews: 331 - Avg Rating: 4.19 - Top Product: B006O37RY4 (10 reviews) - Top Words: shoes(343), these(307), nike(207), shoe(187), pair(137), running(127), comfortable(118), great(118), feet(82), vomero(74) - Product Clues: shoes, nike, shoe Insights for Topic 68: - Reviews: 329 - Avg Rating: 4.24 - Top Product: B003NYUSPM (14 reviews) - Top Words: these(267), shoes(244), shoe(159), great(122), nike(106), comfortable(100), feet(89), socks(71), pair(66), size(63) - Product Clues: shoes, shoe, nike Insights for Topic 73: - Reviews: 328 - Avg Rating: 4.34 - Top Product: B003NYUSPM (27 reviews) - Top Words: these(228), socks(128), great(117), shoes(112), feet(109), comfortable(99), shoe(82), wear(72), nike(63), love(57) - Product Clues: shoes, shoe, nike, boots Insights for Topic 46: - Reviews: 323 - Avg Rating: 4.02 - Top Product: B000V4YZ1K (18 reviews) - Top Words: these(240), shoes(193), shoe(113), great(103), comfortable(99), pair(73), feet(70), little(69), size(66), nike(65) - Product Clues: shoes, shoe, nike Insights for Topic 1: - Reviews: 302 - Avg Rating: 4.32 - Top Product: B000V4YZ1K (11 reviews) - Top Words: these(189), shoes(166), comfortable(100), shoe(97), nike(78), pair(78), great(75), feet(61), size(61), bought(58) - Product Clues: shoes, shoe, nike Insights for Topic 36: - Reviews: 297 - Avg Rating: 4.72 - Top Product: B0036DRWKO (18 reviews) - Top Words: shoes(128), these(125), great(82), loves(64), comfortable(64), grandson(63), thanks(60), love(50), nike(46), happy(46) - Product Clues: shoes, nike, shoe Insights for Topic 38: - Reviews: 296 - Avg Rating: 4.26 - Top Product: B000V4YZ1K (6 reviews) - Top Words: shoes(181), these(148), shoe(119), size(96), great(96), comfortable(90), nike(74), wide(67), love(67), width(64) - Product Clues: shoes, shoe, nike Insights for Topic 21: - Reviews: 292 - Avg Rating: 4.65 - Top Product: B004UBXO9Y (6 reviews) - Top Words: shoes(154), great(106), these(98), love(76), comfortable(66), confortable(60), shoe(59), pair(53), nice(48), nike(48) - Product Clues: shoes, shoe, nike Insights for Topic 4: - Reviews: 284 - Avg Rating: 4.34 - Top Product: B004IM1GHW (5 reviews) - Top Words: shoes(228), these(215), shoe(121), comfortable(108), nike(101), great(90), pair(82), wear(67), feet(58), running(56) - Product Clues: shoes, shoe, nike
import pandas as pd
import matplotlib.pyplot as plt
uniquereviewers = reviews_df['reviewerID'].nunique()
print(f'Number of unique reviewers: {uniquereviewers}') # Total unique reviewers in the dataset
# --- Top Reviewers Script ---
def plot_top_reviewers(df, n=10):
"""
Show top reviewers by number of reviews.
Args:
df: DataFrame with 'reviewerID' column
n: number of top reviewers to display
"""
# Count reviews per reviewer
top_reviewers = df['reviewerID'].value_counts().head(n)
# Print table for reference
print("Top Reviewers:")
print(top_reviewers)
# Plot
plt.figure(figsize=(10, 6))
top_reviewers.plot(kind='bar', color='steelblue', edgecolor='black')
plt.title(f"Top {n} Reviewers by Number of Reviews")
plt.xlabel("Reviewer ID")
plt.ylabel("Number of Reviews")
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.show()
# --- Example usage ---
plot_top_reviewers(reviews_df, n=10)
Number of unique reviewers: 20423 Top Reviewers: reviewerID A32D0TORRTI9E5 11 A265PCQZA1Y1WF 7 A237P6ACWJR9LM 7 ARE2MDLUM3APW 7 A1PR0WW5UQHL7X 6 A3HJOKYEV152QJ 5 A1OTV3X29IALOU 5 A3FP6ZIBTMCPCF 5 AC441KJETNFXS 5 A2J3QP96I96P4B 5 Name: count, dtype: int64
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
def plot_top_reviewer_topics(df, n=10):
"""
Show distribution of topics reviewed by top reviewers.
Args:
df: DataFrame with 'reviewerID' and 'topic' columns
n: number of top reviewers to display
"""
# Get top reviewers
top_reviewers = df['reviewerID'].value_counts().head(n).index
# Filter down to their reviews
subset = df[df['reviewerID'].isin(top_reviewers)]
# Build pivot table: reviewers (rows) x topics (columns)
reviewer_topics = pd.crosstab(subset['reviewerID'], subset['topic'])
# Print table for reference
print("Top Reviewer → Topic counts:")
print(reviewer_topics)
# --- Example usage ---
plot_top_reviewer_topics(reviews_df, n=10)
Top Reviewer → Topic counts: topic 0 2 3 4 5 6 7 8 10 12 14 19 22 23 26 \ reviewerID A1OTV3X29IALOU 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 A1PR0WW5UQHL7X 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 A237P6ACWJR9LM 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 A265PCQZA1Y1WF 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 A2J3QP96I96P4B 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 A32D0TORRTI9E5 0 3 0 0 0 0 0 0 0 0 0 0 1 0 0 A3FP6ZIBTMCPCF 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 A3HJOKYEV152QJ 0 0 0 1 0 0 0 1 0 0 1 1 0 0 0 AC441KJETNFXS 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 ARE2MDLUM3APW 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 topic 27 31 33 35 36 37 38 41 42 43 47 51 56 60 61 \ reviewerID A1OTV3X29IALOU 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 A1PR0WW5UQHL7X 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 A237P6ACWJR9LM 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 A265PCQZA1Y1WF 1 0 0 0 0 0 0 4 0 0 0 0 1 0 1 A2J3QP96I96P4B 1 0 0 1 0 0 0 0 2 0 0 0 0 0 0 A32D0TORRTI9E5 0 0 1 0 0 0 1 0 1 0 0 1 1 0 0 A3FP6ZIBTMCPCF 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 A3HJOKYEV152QJ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 AC441KJETNFXS 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 ARE2MDLUM3APW 0 1 0 2 0 0 0 0 2 0 0 0 0 0 0 topic 64 67 73 74 reviewerID A1OTV3X29IALOU 0 0 0 0 A1PR0WW5UQHL7X 1 0 0 0 A237P6ACWJR9LM 0 0 0 1 A265PCQZA1Y1WF 0 0 0 0 A2J3QP96I96P4B 0 0 1 0 A32D0TORRTI9E5 2 0 0 0 A3FP6ZIBTMCPCF 0 0 0 0 A3HJOKYEV152QJ 0 0 0 0 AC441KJETNFXS 0 1 0 0 ARE2MDLUM3APW 0 0 0 0