|
@@ -127,37 +127,63 @@ valid_channels = main_channels[:8]
|
|
|
log(f"品类数: {len(valid_categories)}, 渠道数: {len(valid_channels)}")
|
|
log(f"品类数: {len(valid_categories)}, 渠道数: {len(valid_channels)}")
|
|
|
log()
|
|
log()
|
|
|
|
|
|
|
|
-log("【各品类最佳渠道】")
|
|
|
|
|
|
|
+# 输出矩阵
|
|
|
|
|
+log("【渠道×品类 回流率矩阵】")
|
|
|
|
|
+log("-" * 100)
|
|
|
|
|
+
|
|
|
|
|
+# 简化渠道名用于表头
|
|
|
|
|
+ch_short = {ch: ch[:8] for ch in valid_channels}
|
|
|
|
|
+header = f"{'品类':<15}" + "".join([f"{ch_short[ch]:>12}" for ch in valid_channels])
|
|
|
|
|
+log(header)
|
|
|
|
|
+log("-" * 100)
|
|
|
|
|
+
|
|
|
|
|
+for category in valid_categories:
|
|
|
|
|
+ if category not in pivot_ror.index:
|
|
|
|
|
+ continue
|
|
|
|
|
+ cat_name = str(category)[:13] if pd.notna(category) else '(空)'
|
|
|
|
|
+ row_str = f"{cat_name:<15}"
|
|
|
|
|
+ for ch in valid_channels:
|
|
|
|
|
+ if ch in pivot_ror.columns and pd.notna(pivot_ror.loc[category, ch]):
|
|
|
|
|
+ rate = pivot_ror.loc[category, ch]
|
|
|
|
|
+ row_str += f"{rate:>12.1%}"
|
|
|
|
|
+ else:
|
|
|
|
|
+ row_str += f"{'--':>12}"
|
|
|
|
|
+ log(row_str)
|
|
|
|
|
+
|
|
|
|
|
+log()
|
|
|
|
|
+
|
|
|
|
|
+log("【各品类 Top 3 渠道】")
|
|
|
log("-" * 80)
|
|
log("-" * 80)
|
|
|
|
|
|
|
|
for category in valid_categories:
|
|
for category in valid_categories:
|
|
|
if category not in pivot_ror.index:
|
|
if category not in pivot_ror.index:
|
|
|
continue
|
|
continue
|
|
|
- row = pivot_ror.loc[category, [c for c in valid_channels if c in pivot_ror.columns]].dropna()
|
|
|
|
|
|
|
+ row = pivot_ror.loc[category, [c for c in valid_channels if c in pivot_ror.columns]].dropna().sort_values(ascending=False)
|
|
|
if len(row) == 0:
|
|
if len(row) == 0:
|
|
|
continue
|
|
continue
|
|
|
- best_ch = row.idxmax()
|
|
|
|
|
- best_ror = row.max()
|
|
|
|
|
- cat_uv = int(pivot_uv.loc[category].sum())
|
|
|
|
|
cat_name = str(category)[:15] if pd.notna(category) else '(空)'
|
|
cat_name = str(category)[:15] if pd.notna(category) else '(空)'
|
|
|
- log(f" {cat_name:<17} UV={cat_uv:>8,} → {best_ch:<20} 回流率={best_ror:.1%}")
|
|
|
|
|
|
|
+ cat_uv = int(pivot_uv.loc[category].sum())
|
|
|
|
|
+ top3 = ", ".join([f"{ch[:10]}({row[ch]:.0%})" for ch in row.head(3).index])
|
|
|
|
|
+ log(f" {cat_name:<17} UV={cat_uv:>8,} → {top3}")
|
|
|
|
|
|
|
|
log()
|
|
log()
|
|
|
|
|
|
|
|
-log("【各渠道最佳品类】")
|
|
|
|
|
|
|
+log("【各渠道 Top 5 品类】")
|
|
|
log("-" * 80)
|
|
log("-" * 80)
|
|
|
|
|
|
|
|
for ch in valid_channels:
|
|
for ch in valid_channels:
|
|
|
if ch not in pivot_ror.columns:
|
|
if ch not in pivot_ror.columns:
|
|
|
continue
|
|
continue
|
|
|
- col = pivot_ror.loc[valid_categories, ch].dropna()
|
|
|
|
|
|
|
+ col = pivot_ror.loc[valid_categories, ch].dropna().sort_values(ascending=False)
|
|
|
if len(col) == 0:
|
|
if len(col) == 0:
|
|
|
continue
|
|
continue
|
|
|
- best_cat = col.idxmax()
|
|
|
|
|
- best_ror = col.max()
|
|
|
|
|
ch_uv = int(channel_stats[channel_stats['channel'] == ch]['点击uv'].values[0])
|
|
ch_uv = int(channel_stats[channel_stats['channel'] == ch]['点击uv'].values[0])
|
|
|
- cat_name = str(best_cat)[:15] if pd.notna(best_cat) else '(空)'
|
|
|
|
|
- log(f" {ch:<25} UV={ch_uv:>10,} → {cat_name:<15} 回流率={best_ror:.1%}")
|
|
|
|
|
|
|
+ log(f" {ch:<25} UV={ch_uv:>10,}")
|
|
|
|
|
+ for cat in col.head(5).index:
|
|
|
|
|
+ cat_name = str(cat)[:15] if pd.notna(cat) else '(空)'
|
|
|
|
|
+ cat_uv = int(pivot_uv.loc[cat, ch]) if ch in pivot_uv.columns else 0
|
|
|
|
|
+ log(f" {cat_name:<17} UV={cat_uv:>8,} 回流率={col[cat]:.1%}")
|
|
|
|
|
+ log()
|
|
|
|
|
|
|
|
log()
|
|
log()
|
|
|
|
|
|