|
| 1 | +# SentimentInsights Export Feature Guide |
| 2 | + |
| 3 | +The SentimentInsights gem now includes comprehensive export functionality for all analysis results. Export your sentiment analysis, entity extraction, and key phrase results to CSV and Excel formats with advanced filtering and customization options. |
| 4 | + |
| 5 | +## 🚀 Quick Start |
| 6 | + |
| 7 | +```ruby |
| 8 | +# Run your analysis as usual |
| 9 | +result = SentimentInsights::Insights::Sentiment.new.analyze(entries) |
| 10 | + |
| 11 | +# Export to CSV (simplest usage) |
| 12 | +result.to_csv("my_analysis.csv") |
| 13 | + |
| 14 | +# Export to Excel |
| 15 | +result.to_excel("my_analysis.xlsx") |
| 16 | + |
| 17 | +# Auto-detect format from filename |
| 18 | +result.export("my_analysis.csv") # Creates CSV |
| 19 | +result.export("my_analysis.xlsx") # Creates Excel |
| 20 | +``` |
| 21 | + |
| 22 | +## 📊 CSV Export Structure |
| 23 | + |
| 24 | +### Sentiment Analysis CSV |
| 25 | +```csv |
| 26 | +response_id,text,sentiment_label,sentiment_score,segment_age_group,segment_region,timestamp |
| 27 | +r_1,"I love this product!",positive,0.9,18-25,North,2024-06-28T10:30:00Z |
| 28 | +r_2,"Service was terrible",negative,-0.8,26-35,South,2024-06-28T10:31:00Z |
| 29 | +
|
| 30 | +SUMMARY STATISTICS |
| 31 | +Total Responses,150 |
| 32 | +Positive Count,90 |
| 33 | +Positive Percentage,60.0% |
| 34 | +Net Sentiment Score,40.0 |
| 35 | +
|
| 36 | +SEGMENT ANALYSIS |
| 37 | +Segment Type,Segment Value,Total Count,Positive %,Neutral %,Negative %,Net Score |
| 38 | +Age Group,18-25,75,65.3%,18.7%,16.0%,49.3 |
| 39 | +Age Group,26-35,45,53.3%,22.2%,24.4%,28.9 |
| 40 | +``` |
| 41 | + |
| 42 | +### Entity Extraction CSV |
| 43 | +```csv |
| 44 | +response_id,text,entities_found,segment_age_group,segment_region,timestamp |
| 45 | +r_1,"Apple released iPhone",apple:ORGANIZATION,iphone:PRODUCT,18-25,North,2024-06-28T10:30:00Z |
| 46 | +
|
| 47 | +SUMMARY STATISTICS |
| 48 | +Total Unique Entities,25 |
| 49 | +Organizations Mentioned,8 |
| 50 | +Most Mentioned Entity,apple (5 times) |
| 51 | +
|
| 52 | +ENTITY DETAILS |
| 53 | +Entity,Type,Total Mentions,Response IDs,Segment Distribution |
| 54 | +apple,ORGANIZATION,5,"r_1,r_3,r_7",age_group_18-25:3,age_group_26-35:2 |
| 55 | +``` |
| 56 | + |
| 57 | +### Key Phrases CSV |
| 58 | +```csv |
| 59 | +response_id,text,sentiment,sentiment_score,key_phrases_found,segment_age_group,timestamp |
| 60 | +r_1,"Great customer service!",positive,0.8,"customer service,great experience",18-25,2024-06-28T10:30:00Z |
| 61 | +
|
| 62 | +PHRASE DETAILS |
| 63 | +Phrase,Total Mentions,Response IDs,Sentiment Distribution,Segment Distribution |
| 64 | +customer service,8,"r_1,r_4,r_7",positive:5,neutral:2,negative:1,age_group_18-25:4 |
| 65 | +``` |
| 66 | + |
| 67 | +## 🎛️ Advanced Export Options |
| 68 | + |
| 69 | +### Basic Configuration |
| 70 | +```ruby |
| 71 | +# Export with custom options |
| 72 | +result.to_csv("analysis.csv", { |
| 73 | + include_summary: true, # Include summary statistics |
| 74 | + include_segments: true, # Include segment analysis |
| 75 | + include_timestamp: true, # Add timestamp column |
| 76 | + timestamp_format: "%Y-%m-%d %H:%M:%S" |
| 77 | +}) |
| 78 | + |
| 79 | +# Skip summary and segments (responses only) |
| 80 | +result.to_csv("responses_only.csv", { |
| 81 | + include_summary: false, |
| 82 | + include_segments: false |
| 83 | +}) |
| 84 | +``` |
| 85 | + |
| 86 | +### Dynamic Segment Handling |
| 87 | +The export system automatically detects and flattens all segment structures: |
| 88 | + |
| 89 | +```ruby |
| 90 | +entries = [ |
| 91 | + { |
| 92 | + answer: "Great product!", |
| 93 | + segment: { |
| 94 | + demographics: { age: "25-34", income: "high" }, |
| 95 | + location: { country: "USA", state: "CA" }, |
| 96 | + simple_field: "value" |
| 97 | + } |
| 98 | + } |
| 99 | +] |
| 100 | + |
| 101 | +result = analyzer.analyze(entries) |
| 102 | +result.to_csv("complex_segments.csv") |
| 103 | + |
| 104 | +# CSV headers will be: |
| 105 | +# response_id,text,sentiment_label,sentiment_score, |
| 106 | +# segment_demographics_age,segment_demographics_income, |
| 107 | +# segment_location_country,segment_location_state, |
| 108 | +# segment_simple_field,timestamp |
| 109 | +``` |
| 110 | + |
| 111 | +## 🔍 Filtering and Custom Exports |
| 112 | + |
| 113 | +### Fluent Interface |
| 114 | +```ruby |
| 115 | +# Method chaining for custom exports |
| 116 | +result |
| 117 | + .responses_only # Skip summary sections |
| 118 | + .filter_sentiment(:positive) # Only positive responses |
| 119 | + .filter_segments(age_group: ["18-25", "26-35"]) # Specific age groups |
| 120 | + .to_csv("young_positive_feedback.csv") |
| 121 | +``` |
| 122 | + |
| 123 | +### Quick Filter Methods |
| 124 | +```ruby |
| 125 | +# Export only positive responses |
| 126 | +result.export_positive(:csv, "positive_feedback.csv") |
| 127 | + |
| 128 | +# Export only negative responses |
| 129 | +result.export_negative(:excel, "issues_to_address.xlsx") |
| 130 | + |
| 131 | +# Export specific segments |
| 132 | +result.export_by_segment(:age_group, ["18-25"], :csv, "young_users.csv") |
| 133 | +result.export_by_segment(:region, ["North", "South"], :excel, "regional_analysis.xlsx") |
| 134 | +``` |
| 135 | + |
| 136 | +### Advanced Filtering |
| 137 | +```ruby |
| 138 | +# Complex filter combinations |
| 139 | +result.exporter({ |
| 140 | + filter: { |
| 141 | + sentiment: [:positive, :neutral], # Exclude negative |
| 142 | + segments: { |
| 143 | + age_group: ["18-25", "26-35"], |
| 144 | + region: ["North", "West"] |
| 145 | + } |
| 146 | + }, |
| 147 | + include_summary: false |
| 148 | +}).to_csv("filtered_analysis.csv") |
| 149 | +``` |
| 150 | + |
| 151 | +## 📈 Excel Export Features |
| 152 | + |
| 153 | +Excel exports include multiple worksheets: |
| 154 | + |
| 155 | +1. **Responses** - Individual response data |
| 156 | +2. **Summary** - Statistical summaries |
| 157 | +3. **Segment Analysis** - Breakdown by segments |
| 158 | +4. **Entity Details** - Entity-specific analysis (entities only) |
| 159 | +5. **Phrase Details** - Phrase-specific analysis (key phrases only) |
| 160 | + |
| 161 | +```ruby |
| 162 | +# Basic Excel export |
| 163 | +result.to_excel("comprehensive_report.xlsx") |
| 164 | + |
| 165 | +# Excel with custom options |
| 166 | +result.to_excel("detailed_report.xlsx", { |
| 167 | + include_summary: true, |
| 168 | + include_segments: true |
| 169 | +}) |
| 170 | +``` |
| 171 | + |
| 172 | +## 🚀 Batch Export |
| 173 | + |
| 174 | +Export to multiple formats at once: |
| 175 | + |
| 176 | +```ruby |
| 177 | +# Export to both CSV and Excel |
| 178 | +files = result.export_all("quarterly_analysis") |
| 179 | +# Returns: { csv: "quarterly_analysis.csv", excel: "quarterly_analysis.xlsx" } |
| 180 | + |
| 181 | +files.each do |format, filename| |
| 182 | + puts "#{format.upcase} exported to: #{filename}" |
| 183 | +end |
| 184 | +``` |
| 185 | + |
| 186 | +## 🔧 Advanced Usage with Exporter Class |
| 187 | + |
| 188 | +For maximum control, use the Exporter class directly: |
| 189 | + |
| 190 | +```ruby |
| 191 | +exporter = result.exporter({ |
| 192 | + include_summary: true, |
| 193 | + include_segments: true, |
| 194 | + filter: { sentiment: [:positive] } |
| 195 | +}) |
| 196 | + |
| 197 | +# Multiple export operations |
| 198 | +csv_file = exporter.to_csv("positive_analysis.csv") |
| 199 | +excel_file = exporter.to_excel("positive_analysis.xlsx") |
| 200 | + |
| 201 | +# Specialized exports |
| 202 | +summary_only = exporter.to_csv_summary_only("summary.csv") |
| 203 | +responses_only = exporter.to_csv_responses_only("responses.csv") |
| 204 | +``` |
| 205 | + |
| 206 | +## 🎯 Use Cases |
| 207 | + |
| 208 | +### Customer Feedback Analysis |
| 209 | +```ruby |
| 210 | +feedback = analyzer.analyze(customer_responses) |
| 211 | + |
| 212 | +# Export all feedback |
| 213 | +feedback.export_all("customer_feedback_analysis") |
| 214 | + |
| 215 | +# Export issues that need attention |
| 216 | +feedback.export_negative(:excel, "issues_to_resolve.xlsx") |
| 217 | + |
| 218 | +# Export by customer segment |
| 219 | +feedback.export_by_segment(:customer_tier, ["premium", "enterprise"], :csv, "premium_feedback.csv") |
| 220 | +``` |
| 221 | + |
| 222 | +### Survey Response Processing |
| 223 | +```ruby |
| 224 | +survey_results = analyzer.analyze(survey_responses) |
| 225 | + |
| 226 | +# Comprehensive report for stakeholders |
| 227 | +survey_results.to_excel("survey_report.xlsx", { |
| 228 | + include_summary: true, |
| 229 | + include_segments: true |
| 230 | +}) |
| 231 | + |
| 232 | +# Quick CSV for data team |
| 233 | +survey_results |
| 234 | + .responses_only |
| 235 | + .to_csv("raw_survey_data.csv") |
| 236 | +``` |
| 237 | + |
| 238 | +### Regional Analysis |
| 239 | +```ruby |
| 240 | +regional_analysis = analyzer.analyze(regional_data) |
| 241 | + |
| 242 | +# Export by region |
| 243 | +%w[North South East West].each do |region| |
| 244 | + regional_analysis.export_by_segment(:region, region, :csv, "#{region.downcase}_analysis.csv") |
| 245 | +end |
| 246 | +``` |
| 247 | + |
| 248 | +## 📋 File Naming |
| 249 | + |
| 250 | +Auto-generated filenames include timestamps: |
| 251 | +- `sentiment_analysis_20240628_103045.csv` |
| 252 | +- `entities_analysis_20240628_103045.xlsx` |
| 253 | +- `key_phrases_analysis_20240628_103045.csv` |
| 254 | + |
| 255 | +## 🛠️ Installation Requirements |
| 256 | + |
| 257 | +Add to your Gemfile: |
| 258 | +```ruby |
| 259 | +gem 'sentiment_insights', '~> 0.3.0' |
| 260 | +gem 'rubyXL', '~> 3.4' # For Excel export support |
| 261 | +``` |
| 262 | + |
| 263 | +## 🔍 Error Handling |
| 264 | + |
| 265 | +```ruby |
| 266 | +begin |
| 267 | + result.to_excel("report.xlsx") |
| 268 | +rescue => e |
| 269 | + puts "Excel export failed: #{e.message}" |
| 270 | + # Fallback to CSV |
| 271 | + result.to_csv("report.csv") |
| 272 | +end |
| 273 | +``` |
| 274 | + |
| 275 | +## 🎉 Integration Examples |
| 276 | + |
| 277 | +### Rails Controller |
| 278 | +```ruby |
| 279 | +class AnalyticsController < ApplicationController |
| 280 | + def export_feedback |
| 281 | + entries = FeedbackResponse.includes(:customer).map do |response| |
| 282 | + { |
| 283 | + answer: response.comment, |
| 284 | + segment: { |
| 285 | + customer_tier: response.customer.tier, |
| 286 | + region: response.customer.region, |
| 287 | + product: response.product_name |
| 288 | + } |
| 289 | + } |
| 290 | + end |
| 291 | + |
| 292 | + result = SentimentInsights::Insights::Sentiment.new.analyze(entries) |
| 293 | + |
| 294 | + filename = result.to_excel("feedback_analysis_#{Date.current}.xlsx") |
| 295 | + |
| 296 | + send_file filename, |
| 297 | + filename: "customer_feedback_analysis.xlsx", |
| 298 | + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" |
| 299 | + end |
| 300 | +end |
| 301 | +``` |
| 302 | + |
| 303 | +### Background Job |
| 304 | +```ruby |
| 305 | +class AnalysisExportJob < ApplicationJob |
| 306 | + def perform(survey_id, email) |
| 307 | + survey = Survey.find(survey_id) |
| 308 | + entries = survey.responses.map { |r| { answer: r.text, segment: r.metadata } } |
| 309 | + |
| 310 | + result = SentimentInsights::Insights::Sentiment.new.analyze(entries) |
| 311 | + files = result.export_all("survey_#{survey_id}_analysis") |
| 312 | + |
| 313 | + AnalysisMailer.send_results(email, files).deliver_now |
| 314 | + end |
| 315 | +end |
| 316 | +``` |
| 317 | + |
| 318 | +## 🚀 Performance Tips |
| 319 | + |
| 320 | +1. **Use filtering** to reduce export size for large datasets |
| 321 | +2. **Skip unnecessary sections** with `responses_only` for faster exports |
| 322 | +3. **Batch processing** - split large datasets before analysis |
| 323 | +4. **Background jobs** for large exports in web applications |
| 324 | + |
| 325 | +The export system is designed to handle dynamic segment structures, large datasets, and provides maximum flexibility for different use cases while maintaining excellent performance. |
0 commit comments