-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path09_data_profiling_analysis.py
More file actions
338 lines (278 loc) · 12.2 KB
/
Copy path09_data_profiling_analysis.py
File metadata and controls
338 lines (278 loc) · 12.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
"""
Example 09: Data Profiling and Statistical Analysis
This example demonstrates comprehensive data profiling capabilities including:
- Statistical profiling and quality assessment
- Distribution analysis and visualization
- Correlation analysis
- Missing value and outlier detection
- Pattern recognition
- Report generation
Use Case:
- Exploratory Data Analysis (EDA)
- Data quality assessment before migration
- Understanding dataset characteristics
- Identifying data issues early
"""
import pandas as pd
import numpy as np
from schema_mapper.profiler import Profiler
from schema_mapper.visualization import DataVisualizer
# ============================================================================
# SETUP: Create Sample E-commerce Dataset
# ============================================================================
print("="*80)
print("DATA PROFILING AND STATISTICAL ANALYSIS EXAMPLE")
print("="*80)
# Generate realistic e-commerce data
np.random.seed(42)
n_customers = 5000
# Create customer data with intentional quality issues
data = {
# Customer demographics
'customer_id': range(1, n_customers + 1),
'age': np.random.randint(18, 85, n_customers),
'annual_income': np.random.normal(55000, 25000, n_customers),
'credit_score': np.random.randint(300, 850, n_customers),
# Purchase behavior
'total_purchases': np.random.poisson(12, n_customers),
'avg_order_value': np.random.gamma(2, 50, n_customers),
'days_since_last_purchase': np.random.exponential(30, n_customers),
'loyalty_points': np.random.randint(0, 10000, n_customers),
# Account info
'account_age_months': np.random.randint(1, 120, n_customers),
'email_verified': np.random.choice([True, False], n_customers, p=[0.85, 0.15]),
# Categorical
'membership_tier': np.random.choice(['Bronze', 'Silver', 'Gold', 'Platinum'],
n_customers, p=[0.5, 0.3, 0.15, 0.05]),
'preferred_category': np.random.choice(['Electronics', 'Clothing', 'Home', 'Books', 'Sports'],
n_customers),
}
df = pd.DataFrame(data)
# Add some data quality issues for profiling to catch
# 1. Missing values (5% in income)
missing_mask = np.random.random(n_customers) < 0.05
df.loc[missing_mask, 'annual_income'] = np.nan
# 2. Missing values (10% in days_since_last_purchase)
missing_mask = np.random.random(n_customers) < 0.10
df.loc[missing_mask, 'days_since_last_purchase'] = np.nan
# 3. Outliers (unrealistic ages)
outlier_indices = np.random.choice(n_customers, 50, replace=False)
df.loc[outlier_indices, 'age'] = np.random.randint(100, 150, 50)
# 4. Add some duplicates
duplicate_indices = np.random.choice(n_customers, 100, replace=False)
df = pd.concat([df, df.iloc[duplicate_indices]], ignore_index=True)
# 5. Add email pattern column
df['email'] = df['customer_id'].apply(lambda x: f'customer{x}@example.com' if x % 20 != 0 else f'invalid_email_{x}')
print(f"\nCreated dataset: {len(df)} rows, {len(df.columns)} columns")
print(f"Columns: {list(df.columns)}\n")
# ============================================================================
# PART 1: BASIC PROFILING
# ============================================================================
print("\n" + "="*80)
print("PART 1: BASIC STATISTICAL PROFILING")
print("="*80)
# Initialize profiler
profiler = Profiler(df, name='ecommerce_customers', show_progress=True)
# Get summary statistics
print("\n1. Summary Statistics")
print("-" * 80)
stats = profiler.get_summary_stats()
print(f"Dataset: {stats['dataset_name']}")
print(f"Rows: {stats['n_rows']:,}")
print(f"Columns: {stats['n_columns']}")
print(f"Memory: {stats['memory_usage_mb']:.2f} MB")
print(f"Duplicate Rows: {stats['duplicate_rows']}")
# Profile individual column
print("\n2. Column-Level Profiling")
print("-" * 80)
age_profile = profiler.profile_column('age')
print(f"\nAge Statistics:")
print(f" Mean: {age_profile['mean']:.1f}")
print(f" Median: {age_profile['median']:.1f}")
print(f" Std Dev: {age_profile['std']:.1f}")
print(f" Min: {age_profile['min']:.1f}")
print(f" Max: {age_profile['max']:.1f}")
print(f" Skewness: {age_profile['skewness']:.2f}")
print(f" Kurtosis: {age_profile['kurtosis']:.2f}")
# ============================================================================
# PART 2: DATA QUALITY ASSESSMENT
# ============================================================================
print("\n" + "="*80)
print("PART 2: DATA QUALITY ASSESSMENT")
print("="*80)
# Overall quality score
print("\n1. Overall Quality Score")
print("-" * 80)
quality = profiler.assess_quality()
print(f"Quality Score: {quality['overall_score']:.1f}/100")
print(f"Interpretation: {quality['interpretation']}")
print(f"\nComponent Scores:")
print(f" Completeness: {quality['completeness_score']:.1f}")
print(f" Uniqueness: {quality['uniqueness_score']:.1f}")
print(f" Validity: {quality['validity_score']:.1f}")
print(f" Consistency: {quality['consistency_score']:.1f}")
# Missing value analysis
print("\n2. Missing Value Analysis")
print("-" * 80)
missing = profiler.analyze_missing_values()
print(f"Total Missing: {missing['total_missing']:,} ({missing['total_missing_percentage']:.2f}%)")
print(f"Columns with Missing Values: {len(missing['columns_with_missing'])}")
if missing['high_missing_columns']:
print(f"High Missing (>50%): {missing['high_missing_columns']}")
print("\nMissing by Column:")
for col, pct in list(missing['missing_percentages'].items())[:5]:
print(f" {col}: {pct:.2f}%")
# Duplicate detection
print("\n3. Duplicate Detection")
print("-" * 80)
duplicates = profiler.detect_duplicates()
print(f"Duplicate Rows: {duplicates['count']} ({duplicates['percentage']:.2f}%)")
print(f"Unique Rows: {duplicates['unique_count']:,}")
# ============================================================================
# PART 3: DISTRIBUTION AND CORRELATION ANALYSIS
# ============================================================================
print("\n" + "="*80)
print("PART 3: DISTRIBUTION AND CORRELATION ANALYSIS")
print("="*80)
# Distribution analysis
print("\n1. Distribution Analysis")
print("-" * 80)
distributions = profiler.analyze_distributions()
for col, dist_info in list(distributions.items())[:3]:
print(f"\n{col}:")
print(f" Type: {dist_info['distribution_type']}")
print(f" Skewness: {dist_info['skewness']:.2f}")
print(f" Kurtosis: {dist_info['kurtosis']:.2f}")
# Cardinality analysis
print("\n2. Cardinality Analysis")
print("-" * 80)
cardinality = profiler.analyze_cardinality()
print(f"High Cardinality Columns: {cardinality['high_cardinality']}")
print(f"Medium Cardinality Columns: {cardinality['medium_cardinality']}")
print(f"Low Cardinality Columns: {cardinality['low_cardinality']}")
# Correlation analysis
print("\n3. Correlation Analysis")
print("-" * 80)
high_corr = profiler.find_correlations(threshold=0.5, method='pearson')
print(f"Found {len(high_corr)} highly correlated pairs (r >= 0.5):\n")
if len(high_corr) > 0:
print(high_corr.head(10).to_string(index=False))
# ============================================================================
# PART 4: ANOMALY AND PATTERN DETECTION
# ============================================================================
print("\n" + "="*80)
print("PART 4: ANOMALY AND PATTERN DETECTION")
print("="*80)
# Detect outliers
print("\n1. Outlier Detection (IQR Method)")
print("-" * 80)
outliers = profiler.detect_anomalies(method='iqr', threshold=1.5)
for col, indices in list(outliers.items())[:3]:
if len(indices) > 0:
print(f"{col}: {len(indices)} outliers detected")
# Pattern recognition
print("\n2. Pattern Recognition")
print("-" * 80)
patterns = profiler.detect_patterns()
print(f"Email Columns: {patterns['email_columns']}")
print(f"Phone Columns: {patterns['phone_columns']}")
print(f"URL Columns: {patterns['url_columns']}")
print(f"Date String Columns: {patterns['date_string_columns']}")
# ============================================================================
# PART 5: VISUALIZATION
# ============================================================================
print("\n" + "="*80)
print("PART 5: VISUALIZATION EXAMPLES")
print("="*80)
print("\nGenerating visualizations...")
# Note: In a real environment, these would display plots
# For this example, we're just demonstrating the API
# 1. Distribution plots
print(" 1. Creating distribution histograms...")
# fig1 = profiler.plot_distributions(
# columns=['age', 'annual_income', 'avg_order_value'],
# color='#34495e',
# kde_color='#e74c3c'
# )
# fig1.savefig('examples/output/distributions.png', dpi=300, bbox_inches='tight')
# 2. Correlation heatmap
print(" 2. Creating correlation matrix...")
# fig2 = profiler.plot_correlations(method='pearson')
# fig2.savefig('examples/output/correlations.png', dpi=300, bbox_inches='tight')
# 3. Missing values visualization
print(" 3. Creating missing values plot...")
# fig3 = profiler.plot_missing_values()
# fig3.savefig('examples/output/missing_values.png', dpi=300, bbox_inches='tight')
# 4. Outlier detection (box plots)
print(" 4. Creating outlier box plots...")
# fig4 = profiler.plot_outliers(columns=['age', 'annual_income', 'credit_score'])
# fig4.savefig('examples/output/outliers.png', dpi=300, bbox_inches='tight')
# 5. Scatter matrix
print(" 5. Creating scatter plot matrix...")
# fig5 = profiler.plot_scatter_matrix(
# columns=['age', 'annual_income', 'total_purchases', 'avg_order_value'],
# color='#34495e',
# diagonal='kde'
# )
# fig5.savefig('examples/output/scatter_matrix.png', dpi=300, bbox_inches='tight')
print("\n(Visualization code commented out - uncomment to generate plots)")
# ============================================================================
# PART 6: COMPREHENSIVE REPORTING
# ============================================================================
print("\n" + "="*80)
print("PART 6: REPORT GENERATION")
print("="*80)
# Generate comprehensive report
print("\n1. Generating Comprehensive Report")
print("-" * 80)
report = profiler.generate_report(output_format='dict')
print("\nReport Sections:")
print(f" - Dataset: {len(report['dataset'])} metrics")
print(f" - Quality: {len(report['quality'])} metrics")
print(f" - Missing Values: {len(report['missing_values'])} metrics")
print(f" - Cardinality: {len(report['cardinality'])} categories")
print(f" - Duplicates: {len(report['duplicates'])} metrics")
print(f" - Patterns: {len(report['patterns'])} pattern types")
print(f" - Distributions: {len(report['distributions'])} columns analyzed")
# Export as JSON
print("\n2. Exporting Report")
print("-" * 80)
json_report = profiler.generate_report(output_format='json')
# with open('examples/output/profiling_report.json', 'w') as f:
# f.write(json_report)
print("Report can be exported to JSON format")
# Export as HTML
html_report = profiler.generate_report(output_format='html')
# with open('examples/output/profiling_report.html', 'w') as f:
# f.write(html_report)
print("Report can be exported to HTML format")
# ============================================================================
# SUMMARY
# ============================================================================
print("\n" + "="*80)
print("PROFILING SUMMARY")
print("="*80)
print(f"""
Dataset: {profiler.name}
Rows: {len(df):,}
Columns: {len(df.columns)}
Quality Score: {quality['overall_score']:.1f}/100
Interpretation: {quality['interpretation']}
Key Findings:
- Missing Values: {missing['total_missing']:,} cells ({missing['total_missing_percentage']:.2f}%)
- Duplicate Rows: {duplicates['count']} ({duplicates['percentage']:.2f}%)
- High Cardinality Columns: {len(cardinality['high_cardinality'])}
- Detected Patterns: {len([p for p in patterns.values() if p])} types
Recommendations:
1. Address {len(missing['high_missing_columns'])} columns with >50% missing values
2. Remove or investigate {duplicates['count']} duplicate rows
3. Review and handle outliers in {len([v for v in outliers.values() if len(v) > 0])} columns
4. Validate email pattern in 'email' column
""")
print("\n" + "="*80)
print("Example completed! Use these profiling capabilities to:")
print(" - Assess data quality before migration")
print(" - Identify data issues early in the pipeline")
print(" - Generate reports for stakeholders")
print(" - Understand dataset characteristics for ML")
print("="*80)