Jelajahi Sumber

feat(渠道效果分析): 热力图颜色按数值渐变

- 回流率:白→绿渐变(值越高越绿)
- UV:白→蓝渐变(值越高越蓝)
- 推荐率:红→黄→绿渐变(低→中→高)
- 移除8渠道限制,显示所有UV>10000的渠道

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
yangxiaohui 2 bulan lalu
induk
melakukan
1c151cb300
1 mengubah file dengan 60 tambahan dan 59 penghapusan
  1. 60 59
      tasks/渠道效果分析/visualize.py

+ 60 - 59
tasks/渠道效果分析/visualize.py

@@ -65,7 +65,8 @@ daily = df.groupby(['dt', 'channel']).apply(
 # ============================================================
 
 # 主要渠道(UV > 10000)
-main_channels = channel_stats[channel_stats['点击uv'] > 10000]['channel'].tolist()[:8]
+# 选择 UV > 10000 的所有渠道
+main_channels = channel_stats[channel_stats['点击uv'] > 10000]['channel'].tolist()
 valid_categories = pivot_uv[pivot_uv.sum(axis=1) >= 1000].index.tolist()
 heatmap_cols = [c for c in main_channels if c in pivot_ror.columns]
 
@@ -80,15 +81,18 @@ for _, row in channel_stats.iterrows():
         f"<td><div style='background:#007bff;height:20px;width:{bar_width}%'></div></td></tr>"
     )
 
-# 2. 回流率热力图
-def get_cell_class(val):
-    if val is None:
-        return ""
-    if val > 0.30:
-        return "high"
-    if val > 0.15:
-        return "medium"
-    return "low"
+# 2. 回流率热力图 - 根据数值渐变颜色
+def get_ror_color(val, max_val=0.5):
+    """回流率颜色:白色(0) -> 绿色(max)"""
+    if val is None or val <= 0:
+        return "background: #f8f9fa"
+    ratio = min(val / max_val, 1.0)
+    # 白色到绿色渐变
+    r = int(255 - ratio * 215)  # 255 -> 40
+    g = int(255 - ratio * 88)   # 255 -> 167
+    b = int(255 - ratio * 186)  # 255 -> 69
+    text_color = "white" if ratio > 0.5 else "black"
+    return f"background: rgb({r},{g},{b}); color: {text_color}"
 
 ror_header = "<tr><th>品类</th>" + "".join([f"<th>{c[:10]}</th>" for c in heatmap_cols]) + "</tr>"
 ror_rows = []
@@ -97,21 +101,24 @@ for cat in valid_categories:
     for ch in heatmap_cols:
         if ch in pivot_ror.columns and pd.notna(pivot_ror.loc[cat, ch]):
             val = pivot_ror.loc[cat, ch]
-            cls = get_cell_class(val)
-            cells.append(f'<td class="{cls}">{val:.4f}</td>')
+            style = get_ror_color(val)
+            cells.append(f'<td style="{style}">{val:.4f}</td>')
         else:
             cells.append("<td>-</td>")
     ror_rows.append("<tr>" + "".join(cells) + "</tr>")
 
-# 3. UV分布热力图
-def get_uv_class(val):
-    if val >= 50000:
-        return "high"
-    if val >= 10000:
-        return "medium"
-    if val >= 1000:
-        return "low"
-    return ""
+# 3. UV分布热力图 - 根据数值渐变颜色
+def get_uv_color(val, max_val=100000):
+    """UV颜色:白色(0) -> 蓝色(max)"""
+    if val is None or val <= 0:
+        return "background: #f8f9fa"
+    ratio = min(val / max_val, 1.0)
+    # 白色到蓝色渐变
+    r = int(255 - ratio * 201)  # 255 -> 54
+    g = int(255 - ratio * 93)   # 255 -> 162
+    b = int(255 - ratio * 20)   # 255 -> 235
+    text_color = "white" if ratio > 0.5 else "black"
+    return f"background: rgb({r},{g},{b}); color: {text_color}"
 
 uv_header = "<tr><th>品类</th>" + "".join([f"<th>{c[:10]}</th>" for c in heatmap_cols]) + "</tr>"
 uv_rows = []
@@ -121,8 +128,8 @@ for cat in valid_categories:
         if ch in pivot_uv.columns:
             val = pivot_uv.loc[cat, ch]
             if val > 0:
-                cls = get_uv_class(val)
-                cells.append(f'<td class="{cls}">{int(val):,}</td>')
+                style = get_uv_color(val)
+                cells.append(f'<td style="{style}">{int(val):,}</td>')
             else:
                 cells.append("<td>-</td>")
         else:
@@ -135,12 +142,26 @@ pivot_recommend = df.groupby(['channel', 'merge一级品类']).apply(
     include_groups=False
 ).unstack()
 
-def get_recommend_class(val):
+def get_recommend_color(val):
+    """推荐率颜色:红色(低) -> 黄色(中) -> 绿色(高)"""
+    if val is None:
+        return "background: #f8f9fa"
     if val >= 0.8:
-        return "high"
-    if val >= 0.7:
-        return "medium"
-    return "low"
+        ratio = min((val - 0.8) / 0.2, 1.0)
+        r, g, b = 40, 167, 69  # 绿色
+    elif val >= 0.7:
+        ratio = (val - 0.7) / 0.1
+        r = int(255 - ratio * 215)
+        g = int(193 - ratio * 26)
+        b = int(7 + ratio * 62)
+    else:
+        ratio = val / 0.7
+        r, g, b = 220, 53, 69  # 红色基础
+        r = int(255 - ratio * 35)
+        g = int(255 - ratio * 62)
+        b = int(255 - ratio * 248)
+    text_color = "white" if val >= 0.75 or val < 0.65 else "black"
+    return f"background: rgb({r},{g},{b}); color: {text_color}"
 
 recommend_rows = []
 for cat in valid_categories:
@@ -148,8 +169,8 @@ for cat in valid_categories:
     for ch in heatmap_cols:
         if ch in pivot_recommend.columns and cat in pivot_recommend.index and pd.notna(pivot_recommend.loc[cat, ch]):
             val = pivot_recommend.loc[cat, ch]
-            cls = get_recommend_class(val)
-            cells.append(f'<td class="{cls}">{val:.4f}</td>')
+            style = get_recommend_color(val)
+            cells.append(f'<td style="{style}">{val:.4f}</td>')
         else:
             cells.append("<td>-</td>")
     recommend_rows.append("<tr>" + "".join(cells) + "</tr>")
@@ -186,8 +207,8 @@ for cat2 in valid_cat2_labels:
     for ch in heatmap_cols:
         if ch in pivot_cat2_ror.columns and pd.notna(pivot_cat2_ror.loc[cat2, ch]):
             val = pivot_cat2_ror.loc[cat2, ch]
-            cls = get_cell_class(val)
-            cells.append(f'<td class="{cls}">{val:.4f}</td>')
+            style = get_ror_color(val)
+            cells.append(f'<td style="{style}">{val:.4f}</td>')
         else:
             cells.append("<td>-</td>")
     cat2_ror_rows.append("<tr>" + "".join(cells) + "</tr>")
@@ -202,8 +223,8 @@ for cat2 in valid_cat2_labels:
         if ch in pivot_cat2_uv.columns:
             val = pivot_cat2_uv.loc[cat2, ch]
             if val > 0:
-                cls = get_uv_class(val)
-                cells.append(f'<td class="{cls}">{int(val):,}</td>')
+                style = get_uv_color(val)
+                cells.append(f'<td style="{style}">{int(val):,}</td>')
             else:
                 cells.append("<td>-</td>")
         else:
@@ -325,11 +346,7 @@ html_content = f"""<!DOCTYPE html>
 
         <h2>2. 渠道×品类 回流率矩阵</h2>
         <div class="chart-container heatmap matrix-section">
-            <div class="legend">
-                <span class="high">高 &gt;0.30</span>
-                <span class="medium">中 0.15-0.30</span>
-                <span class="low">低 &lt;0.15</span>
-            </div>
+            <div class="legend">颜色越深=回流率越高(白→绿渐变,max=0.50)</div>
             <table>
                 {ror_header}
                 {"".join(ror_rows)}
@@ -338,11 +355,7 @@ html_content = f"""<!DOCTYPE html>
 
         <h2>3. 渠道×品类 点击UV矩阵</h2>
         <div class="chart-container heatmap matrix-section">
-            <div class="legend">
-                <span class="high">高 &gt;5万</span>
-                <span class="medium">中 1-5万</span>
-                <span class="low">低 &lt;1万</span>
-            </div>
+            <div class="legend">颜色越深=UV越高(白→蓝渐变,max=10万)</div>
             <table>
                 {uv_header}
                 {"".join(uv_rows)}
@@ -351,11 +364,7 @@ html_content = f"""<!DOCTYPE html>
 
         <h2>4. 渠道×品类 进入推荐率矩阵</h2>
         <div class="chart-container heatmap matrix-section">
-            <div class="legend">
-                <span class="high">高 &gt;0.80</span>
-                <span class="medium">中 0.70-0.80</span>
-                <span class="low">低 &lt;0.70</span>
-            </div>
+            <div class="legend">颜色:红(&lt;0.70) → 黄(0.70-0.80) → 绿(&gt;0.80)</div>
             <table>
                 {ror_header}
                 {"".join(recommend_rows)}
@@ -364,11 +373,7 @@ html_content = f"""<!DOCTYPE html>
 
         <h2>5. 渠道×二级品类 回流率矩阵</h2>
         <div class="chart-container heatmap matrix-section">
-            <div class="legend">
-                <span class="high">高 &gt;0.30</span>
-                <span class="medium">中 0.15-0.30</span>
-                <span class="low">低 &lt;0.15</span>
-            </div>
+            <div class="legend">颜色越深=回流率越高(白→绿渐变,max=0.50)</div>
             <table>
                 {cat2_ror_header}
                 {"".join(cat2_ror_rows)}
@@ -377,11 +382,7 @@ html_content = f"""<!DOCTYPE html>
 
         <h2>6. 渠道×二级品类 点击UV矩阵</h2>
         <div class="chart-container heatmap matrix-section">
-            <div class="legend">
-                <span class="high">高 &gt;5万</span>
-                <span class="medium">中 1-5万</span>
-                <span class="low">低 &lt;1万</span>
-            </div>
+            <div class="legend">颜色越深=UV越高(白→蓝渐变,max=10万)</div>
             <table>
                 {cat2_ror_header}
                 {"".join(cat2_uv_rows)}