import streamlit as st import pandas as pd from pathlib import Path from collections import Counter import re st.set_page_config(page_title="Customer Experience Analyzer", layout="wide") # Load data DATA_PATH = Path(__file__).parent / "reviews.csv" df = pd.read_csv(DATA_PATH) # Title st.title("Customer Experience Analyzer") st.write("Analyze customer sentiment from restaurant reviews and identify where customer experience can improve.") # Sidebar st.sidebar.header("Filters") selected_sentiment = st.sidebar.multiselect( "Select sentiment", options=df["sentiment"].unique(), default=df["sentiment"].unique() ) search_term = st.sidebar.text_input("Search reviews by keyword") filtered_df = df[df["sentiment"].isin(selected_sentiment)] if search_term: filtered_df = filtered_df[ filtered_df["review_text"].str.contains(search_term, case=False, na=False) ] # KPIs total_reviews = len(filtered_df) positive_rate = (filtered_df["sentiment"] == "positive").mean() * 100 if total_reviews > 0 else 0 negative_rate = (filtered_df["sentiment"] == "negative").mean() * 100 if total_reviews > 0 else 0 st.subheader("Overview") col1, col2, col3 = st.columns(3) col1.metric("Total Reviews", total_reviews) col2.metric("Positive %", f"{positive_rate:.1f}%") col3.metric("Negative %", f"{negative_rate:.1f}%") # Chart st.subheader("Sentiment Breakdown") if total_reviews > 0: st.bar_chart(filtered_df["sentiment"].value_counts()) else: st.warning("No reviews match the selected filters.") # Key complaint drivers st.subheader("Key Complaint Drivers") negative_reviews = filtered_df[filtered_df["sentiment"] == "negative"]["review_text"] if len(negative_reviews) > 0: all_text = " ".join(negative_reviews.astype(str)).lower() words = re.findall(r"\b[a-z]+\b", all_text) stopwords = { "the", "and", "was", "were", "is", "it", "to", "of", "for", "in", "a", "an", "this", "that", "with", "on", "at", "my", "our", "we", "i", "had", "but", "very", "so", "not", "be", "been", "are", "as", "they", "them", "you", "he", "she", "his", "her", "their", "there", "here", "have", "has", "from", "too", "all", "will", "would", "back", "one", "get", "got", "go", "went", "also", "even", "still", "really", "just", "make", "made", "time", "day", "thing", "things", "place", "again", "ever", "only", "your", "good", "like", "food" } complaint_keywords = { "slow", "rude", "cold", "dirty", "bad", "worst", "terrible", "awful", "expensive", "overpriced", "late", "poor", "disappointing", "unfriendly", "noisy", "dry", "burnt", "bland", "tasteless", "small", "waiting", "minutes", "service", "staff", "manager", "order", "orders", "table", "wrong", "delay", "delayed", "undercooked", "overcooked", "stale" } filtered_words = [ word for word in words if word not in stopwords and word in complaint_keywords ] if filtered_words: word_counts = Counter(filtered_words).most_common(10) word_df = pd.DataFrame(word_counts, columns=["Word", "Count"]) st.bar_chart(word_df.set_index("Word")) else: st.info("No complaint keywords found in the current selection.") else: st.info("No negative reviews available.") # Example reviews st.subheader("Example Customer Reviews") col4, col5 = st.columns(2) positive_examples = filtered_df[filtered_df["sentiment"] == "positive"] negative_examples = filtered_df[filtered_df["sentiment"] == "negative"] with col4: st.markdown("### Positive Review Example") if len(positive_examples) > 0: st.success(positive_examples.iloc[0]["review_text"]) else: st.info("No positive review found for this selection.") with col5: st.markdown("### Negative Review Example") if len(negative_examples) > 0: st.error(negative_examples.iloc[0]["review_text"]) else: st.info("No negative review found for this selection.") # Key insights st.subheader("Key Insights") if total_reviews > 0: if positive_rate > negative_rate: st.write("Customer sentiment is mostly positive in the selected reviews.") elif negative_rate > positive_rate: st.write("Customer sentiment is mostly negative in the selected reviews.") else: st.write("Customer sentiment is evenly split between positive and negative.") st.write( f""" - Out of **{total_reviews}** filtered reviews, **{positive_rate:.1f}%** are positive and **{negative_rate:.1f}%** are negative. - This helps management quickly assess overall customer satisfaction. - Searching by keyword can help identify specific issues in customer feedback. """ ) else: st.write("No insights available because no reviews match the selected filters.") # Recommendations st.subheader("Manager Recommendations") if total_reviews > 0: if negative_rate > 60: st.warning("Customer dissatisfaction is high. Management should urgently review repeated complaints and investigate operational issues.") elif negative_rate > 40: st.info("Customer sentiment is mixed. Management should identify recurring negative themes and improve consistency.") else: st.success("Customer sentiment is mostly positive. Management should preserve strengths and continue monitoring feedback.") else: st.write("No recommendation available.") # Reviews table st.subheader("Filtered Reviews Table") if total_reviews > 0: st.dataframe( filtered_df[["review_text", "sentiment"]].reset_index(drop=True), use_container_width=True ) else: st.write("No reviews to display.") # Assistant st.subheader("Ask the Assistant") question = st.text_input("Ask a question about the reviews") if question: q = question.lower() if "positive" in q: st.write("Positive reviews suggest that customers were satisfied with their restaurant experience.") elif "negative" in q: st.write("Negative reviews suggest that customers experienced problems that may affect satisfaction and loyalty.") elif "complaint" in q or "complaints" in q: if len(negative_reviews) > 0 and filtered_words: top_word = word_counts[0][0] st.write(f"A common complaint-related word in the selected reviews is **{top_word}**.") else: st.write("There are no complaint words available in the current selection.") elif "improve" in q or "improvement" in q: st.write("Management should focus on recurring negative feedback and investigate the causes behind poor customer experiences.") else: st.write("This dashboard helps management understand customer sentiment, complaint patterns, and possible improvement areas.")