Spaces:
Build error
Build error
| # Author: Jivan Jamdar | |
| # Date: 2023-10-01 Time: 20:57:43PM | |
| # Description: Streamlit app for sentiment analysis using TextBlob and VADER | |
| import streamlit as st | |
| import pandas as pd | |
| import plotly.express as px | |
| from analyzer import SentimentAnalyzer | |
| def main(): | |
| st.set_page_config( | |
| page_title="Sentiment Analysis App", | |
| page_icon="📊", | |
| layout="wide" | |
| ) | |
| st.title("📊 Sentiment Analysis Tool") | |
| st.write("Analyze the sentiment of tweets, product reviews, or any text!") | |
| analyzer = SentimentAnalyzer() | |
| # different tabs => different functionalities | |
| tab1, tab2, tab3 = st.tabs(["Single Text Analysis", "Batch Analysis", "About"]) | |
| with tab1: | |
| st.subheader("Single Text Analysis") | |
| # tool selection | |
| analysis_tool = st.radio( | |
| "Select analysis tool:", | |
| ["TextBlob", "VADER"], | |
| horizontal=True | |
| ) | |
| # text input | |
| text_input = st.text_area( | |
| "Enter text to analyze:", | |
| height=150, | |
| placeholder="Type or paste your text here..." | |
| ) | |
| if st.button("Analyze Sentiment"): | |
| if text_input: | |
| with st.spinner("Analyzing..."): | |
| if analysis_tool == "TextBlob": | |
| result = analyzer.analyze_textblob(text_input) | |
| method = "TextBlob" | |
| else: | |
| result = analyzer.analyze_vader(text_input) | |
| method = "VADER" | |
| # display results with columns | |
| st.subheader("Results") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown(f"### {result['emoji']} {result['sentiment']}") | |
| st.write(f"Analysis method: {method}") | |
| with col2: | |
| if method == "TextBlob": | |
| st.metric("Polarity", f"{result['polarity']:.2f}") | |
| st.metric("Subjectivity", f"{result['subjectivity']:.2f}") | |
| else: # VADER | |
| st.metric("Compound Score", f"{result['compound']:.2f}") | |
| # detailed breakdown for VADER | |
| if method == "VADER": | |
| st.subheader("Sentiment Breakdown") | |
| vader_df = pd.DataFrame({ | |
| 'Sentiment': ['Positive', 'Neutral', 'Negative'], | |
| 'Score': [result['pos'], result['neu'], result['neg']] | |
| }) | |
| fig = px.bar( | |
| vader_df, | |
| x='Sentiment', | |
| y='Score', | |
| color='Sentiment', | |
| color_discrete_map={ | |
| 'Positive': '#2ECC71', | |
| 'Neutral': '#3498DB', | |
| 'Negative': '#E74C3C' | |
| } | |
| ) | |
| st.plotly_chart(fig, use_container_width=True) | |
| else: | |
| st.warning("Please enter some text to analyze.") | |
| with tab2: | |
| st.subheader("Batch Analysis") | |
| st.write("Upload a CSV or Excel file with a column containing text to analyze multiple entries at once.") | |
| uploaded_file = st.file_uploader("Upload your file", type=["csv", "xlsx"]) | |
| if uploaded_file is not None: | |
| try: | |
| if uploaded_file.name.endswith('.csv'): | |
| df = pd.read_csv(uploaded_file) | |
| else: | |
| df = pd.read_excel(uploaded_file) | |
| st.write("Preview of uploaded data:") | |
| st.dataframe(df.head()) | |
| text_column = st.selectbox("Select the column containing text to analyze:", df.columns) | |
| analysis_tool = st.radio( | |
| "Select analysis tool for batch processing:", | |
| ["TextBlob", "VADER"], | |
| horizontal=True | |
| ) | |
| if st.button("Run Batch Analysis"): | |
| with st.spinner("Analyzing all entries..."): | |
| results = [] | |
| for text in df[text_column]: | |
| if pd.notna(text): # skip NaN values | |
| if analysis_tool == "TextBlob": | |
| result = analyzer.analyze_textblob(str(text)) | |
| else: | |
| result = analyzer.analyze_vader(str(text)) | |
| results.append(result) | |
| else: | |
| # handle NaN values | |
| results.append({ | |
| 'sentiment': 'Unknown', | |
| 'emoji': '❓', | |
| 'compound' if analysis_tool == "VADER" else 'polarity': 0 | |
| }) | |
| # create results DataFrame | |
| results_df = pd.DataFrame(results) | |
| df_with_sentiment = pd.concat([df, results_df], axis=1) | |
| st.subheader("Results") | |
| st.dataframe(df_with_sentiment) | |
| # download button for results | |
| st.download_button( | |
| label="Download Results", | |
| data=df_with_sentiment.to_csv(index=False), | |
| file_name="sentiment_analysis_results.csv", | |
| mime="text/csv" | |
| ) | |
| # show summary statistics | |
| st.subheader("Sentiment Distribution") | |
| sentiment_counts = results_df['sentiment'].value_counts().reset_index() | |
| sentiment_counts.columns = ['Sentiment', 'Count'] | |
| fig = px.pie( | |
| sentiment_counts, | |
| names='Sentiment', | |
| values='Count', | |
| color='Sentiment', | |
| color_discrete_map={ | |
| 'Positive': '#2ECC71', | |
| 'Neutral': '#3498DB', | |
| 'Negative': '#E74C3C', | |
| 'Unknown': '#95A5A6' | |
| } | |
| ) | |
| st.plotly_chart(fig, use_container_width=True) | |
| except Exception as e: | |
| st.error(f"Error processing the uploaded file: {str(e)}") | |
| with tab3: | |
| st.subheader("About This App") | |
| st.write(""" | |
| This Sentiment Analysis App uses two popular techniques: | |
| 1. **TextBlob**: A simple NLP library that provides a simple API for diving into common NLP tasks. | |
| - Polarity: Score from -1 (very negative) to +1 (very positive) | |
| - Subjectivity: Score from 0 (objective) to 1 (subjective) | |
| 2. **VADER** (Valence Aware Dictionary and sEntiment Reasoner): A lexicon and rule-based sentiment analysis tool specifically attuned to sentiments expressed in social media. | |
| - Compound: Normalized score from -1 (very negative) to +1 (very positive) | |
| - Positive, Neutral, Negative: Proportions of text that fall in each category | |
| ### When to use each tool: | |
| - TextBlob is simpler and works well for general text | |
| - VADER is better for social media content, slang, and emoticons | |
| ### Limitations: | |
| - Neither tool understands sarcasm well | |
| - Context is often missed | |
| - Language specific (works best with English) | |
| """) | |
| if __name__ == "__main__": | |
| main() |