|
@@ -8,80 +8,96 @@ import time
|
|
import random
|
|
import random
|
|
from collections import defaultdict
|
|
from collections import defaultdict
|
|
import matplotlib.pyplot as plt
|
|
import matplotlib.pyplot as plt
|
|
|
|
+import numpy as np
|
|
|
|
|
|
-plt.rcParams['font.sans-serif'] = ['SimHei']
|
|
+
|
|
-plt.rcParams['axes.unicode_minus'] = False
|
|
|
|
-
|
|
|
|
-
|
|
|
|
class ReportGenerator:
|
|
class ReportGenerator:
|
|
- def __init__(self, data, anomalies, segments, action_stats, product_stats, channel_stats):
|
|
+ def __init__(self, data, anomalies, segments, process_stats, action_stats, product_stats, channel_stats):
|
|
self.data = data
|
|
self.data = data
|
|
self.anomalies = anomalies
|
|
self.anomalies = anomalies
|
|
self.segments = segments
|
|
self.segments = segments
|
|
|
|
+ self.process_stats = process_stats
|
|
self.action_stats = action_stats
|
|
self.action_stats = action_stats
|
|
self.product_stats = product_stats
|
|
self.product_stats = product_stats
|
|
self.channel_stats = channel_stats
|
|
self.channel_stats = channel_stats
|
|
|
|
|
|
def generate(self):
|
|
def generate(self):
|
|
|
|
|
|
-
|
|
|
|
report = {
|
|
report = {
|
|
- 'total_users': len(set([item['user'] for item in self.data])),
|
|
+ 'total_users': len(set([user_actions['user'] for user_actions in self.data])),
|
|
- 'total_actions': len(self.data),
|
|
+ 'total_actions': sum(len(user_actions['actions']) for user_actions in self.data),
|
|
'anomalies': self.anomalies,
|
|
'anomalies': self.anomalies,
|
|
'user_segments': self.segments,
|
|
'user_segments': self.segments,
|
|
|
|
+ 'process_stats': self.process_stats,
|
|
'action_stats': self.action_stats,
|
|
'action_stats': self.action_stats,
|
|
'product_stats': self.product_stats,
|
|
'product_stats': self.product_stats,
|
|
'channel_stats': self.channel_stats
|
|
'channel_stats': self.channel_stats
|
|
}
|
|
}
|
|
- self.plot_action_stats(self.action_stats)
|
|
+
|
|
- self.plot_product_stats(self.product_stats)
|
|
+
|
|
- self.plot_channel_stats(self.channel_stats)
|
|
+ print("Report Summary:")
|
|
|
|
+ print(f"Total Users: {report['total_users']}")
|
|
|
|
+ print(f"Total Actions: {report['total_actions']}")
|
|
|
|
+ print(f"Anomalies: {report['anomalies']}")
|
|
|
|
+ print(f"User Segments: {report['user_segments']}")
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ for process, actions in self.process_stats.items():
|
|
|
|
+ self.plot_bar(actions, f"{process} Funnel")
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ self.plot_stats(self.action_stats, "Action Statistics")
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ self.plot_stats(self.product_stats, "Product Statistics")
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ self.plot_stats(self.channel_stats, "Channel Statistics")
|
|
|
|
+
|
|
return report
|
|
return report
|
|
|
|
|
|
- def plot_action_stats(self, action_stats):
|
|
+ def plot_stats(self, stats, title):
|
|
- if not action_stats:
|
|
+
|
|
- print("No data for action stats.")
|
|
+ labels, values = zip(*stats.items())
|
|
- return
|
|
+ plt.figure(figsize=(12, 6))
|
|
-
|
|
+ plt.bar(labels, values)
|
|
- actions = list(action_stats.keys())
|
|
+ plt.title(title)
|
|
- counts = list(action_stats.values())
|
|
+ plt.xticks(rotation=45, ha='right', fontsize=10)
|
|
- plt.figure(figsize=(12, 8))
|
|
+ plt.tight_layout()
|
|
- plt.bar(actions, counts, color='skyblue')
|
|
|
|
- plt.xlabel('行为', fontsize=12)
|
|
|
|
- plt.ylabel('次数', fontsize=12)
|
|
|
|
- plt.title('行为统计', fontsize=14)
|
|
|
|
- plt.xticks(rotation=45, fontsize=10)
|
|
|
|
- plt.yticks(fontsize=10)
|
|
|
|
- plt.tight_layout()
|
|
|
|
-
|
|
|
|
-
|
|
|
|
plt.show()
|
|
plt.show()
|
|
|
|
|
|
- def plot_product_stats(self, product_stats):
|
|
+ def plot_bar(self, actions, title):
|
|
- if not product_stats:
|
|
+
|
|
- print("No data for product stats.")
|
|
+ labels = list(actions.keys())
|
|
- return
|
|
+ values = list(actions.values())
|
|
-
|
|
+
|
|
- products = list(product_stats.keys())
|
|
+
|
|
- counts = list(product_stats.values())
|
|
+ sorted_indices = np.argsort(values)
|
|
- plt.figure(figsize=(10, 6))
|
|
+ labels = np.array(labels)[sorted_indices].tolist()
|
|
- plt.bar(products, counts, color='lightgreen')
|
|
+ values = np.array(values)[sorted_indices].tolist()
|
|
- plt.xlabel('产品')
|
|
+
|
|
- plt.ylabel('次数')
|
|
+
|
|
- plt.title('产品统计')
|
|
+ positions = np.arange(len(labels))
|
|
|
|
+
|
|
|
|
+ fig, ax = plt.subplots(figsize=(10, 6))
|
|
|
|
+ ax.barh(positions, values, color='teal')
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ for i, value in enumerate(values):
|
|
|
|
+ ax.text(value, positions[i], str(value),
|
|
|
|
+ ha='right', va='center', color='black', fontsize=10)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ ax.set_yticks(positions)
|
|
|
|
+ ax.set_yticklabels(labels)
|
|
|
|
+ ax.set_xlabel('Number of Actions')
|
|
|
|
+ ax.set_ylabel('Behavior')
|
|
|
|
+
|
|
|
|
+ ax.set_title(title)
|
|
|
|
+
|
|
|
|
+ plt.tight_layout()
|
|
plt.show()
|
|
plt.show()
|
|
|
|
|
|
- def plot_channel_stats(self, channel_stats):
|
|
+
|
|
- if not channel_stats:
|
|
+plt.rcParams['font.sans-serif'] = ['SimHei']
|
|
- print("No data for channel stats.")
|
|
+plt.rcParams['axes.unicode_minus'] = False
|
|
- return
|
|
|
|
-
|
|
|
|
- channels = list(channel_stats.keys())
|
|
|
|
- counts = list(channel_stats.values())
|
|
|
|
- plt.figure(figsize=(10, 6))
|
|
|
|
- plt.bar(channels, counts, color='orange')
|
|
|
|
- plt.xlabel('渠道')
|
|
|
|
- plt.ylabel('次数')
|
|
|
|
- plt.title('渠道统计')
|
|
|
|
- plt.show()
|
|
|