mirror of
https://github.com/primedigitaltech/market-assistant.git
synced 2026-07-22 08:01:34 +08:00
fix(report): align shop/brand pie denominators with §4 CR table via mix tail bucket
Made-with: Cursor
This commit is contained in:
parent
e20250e7a6
commit
c3fdb2b970
@ -1322,6 +1322,26 @@ def _brand_cr(cnames: list[str]) -> tuple[float | None, float | None, str, str]:
|
|||||||
return cr1, cr3, top1, f"{100.0 * top1_n / total:.1f}%"
|
return cr1, cr3, top1, f"{100.0 * top1_n / total:.1f}%"
|
||||||
|
|
||||||
|
|
||||||
|
def _counter_mix_top_rows_with_remainder(
|
||||||
|
row_names: list[str], *, top_n: int, remainder_label: str
|
||||||
|
) -> list[tuple[str, int]]:
|
||||||
|
"""
|
||||||
|
与 §4 集中度表、饼图一致:按行计数;``most_common(top_n)`` 未覆盖的长尾合并为
|
||||||
|
``remainder_label``,保证 ``sum(count) == len(row_names)``(仅统计非空名行)。
|
||||||
|
"""
|
||||||
|
c = Counter((x or "").strip() for x in row_names if (x or "").strip())
|
||||||
|
if not c:
|
||||||
|
return []
|
||||||
|
total = sum(c.values())
|
||||||
|
common = c.most_common(top_n)
|
||||||
|
accounted = sum(v for _, v in common)
|
||||||
|
rest = total - accounted
|
||||||
|
out: list[tuple[str, int]] = list(common)
|
||||||
|
if rest > 0:
|
||||||
|
out.append((remainder_label, rest))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def _price_stats_extended(prices: list[float]) -> dict[str, Any]:
|
def _price_stats_extended(prices: list[float]) -> dict[str, Any]:
|
||||||
if not prices:
|
if not prices:
|
||||||
return {}
|
return {}
|
||||||
@ -2136,7 +2156,7 @@ def build_competitor_markdown(
|
|||||||
_embed_chart(
|
_embed_chart(
|
||||||
run_dir,
|
run_dir,
|
||||||
"chart_brand_rows_pie.png",
|
"chart_brand_rows_pie.png",
|
||||||
"品牌列表曝光占比(扇形图,Top 段合并为「其他」;与上表集中度同源)",
|
"品牌列表曝光占比(扇形图;与上表按行计同源,长尾并入「(其余品牌)」;扇形内再合并为「其他」)",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
lines.extend(
|
lines.extend(
|
||||||
@ -2178,7 +2198,7 @@ def build_competitor_markdown(
|
|||||||
_embed_chart(
|
_embed_chart(
|
||||||
run_dir,
|
run_dir,
|
||||||
"chart_shop_rows_pie.png",
|
"chart_shop_rows_pie.png",
|
||||||
"店铺列表曝光占比(扇形图;与上表同源)",
|
"店铺列表曝光占比(扇形图;与上表按行计同源,长尾并入「(其余店铺)」)",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
lines.extend(
|
lines.extend(
|
||||||
@ -2798,15 +2818,19 @@ def build_competitor_brief(
|
|||||||
],
|
],
|
||||||
"list_brand_mix_top": [
|
"list_brand_mix_top": [
|
||||||
{"label": k, "count": v}
|
{"label": k, "count": v}
|
||||||
for k, v in Counter(
|
for k, v in _counter_mix_top_rows_with_remainder(
|
||||||
b for b in brands_s if (b or "").strip()
|
brands_s,
|
||||||
).most_common(24)
|
top_n=24,
|
||||||
|
remainder_label="(其余品牌)",
|
||||||
|
)
|
||||||
],
|
],
|
||||||
"list_shop_mix_top": [
|
"list_shop_mix_top": [
|
||||||
{"label": k, "count": v}
|
{"label": k, "count": v}
|
||||||
for k, v in Counter(
|
for k, v in _counter_mix_top_rows_with_remainder(
|
||||||
s for s in shops_s if (s or "").strip()
|
shops_s,
|
||||||
).most_common(24)
|
top_n=24,
|
||||||
|
remainder_label="(其余店铺)",
|
||||||
|
)
|
||||||
],
|
],
|
||||||
"price_stats": pst,
|
"price_stats": pst,
|
||||||
"price_stats_source": price_stats_source,
|
"price_stats_source": price_stats_source,
|
||||||
|
|||||||
@ -200,3 +200,18 @@ class BuildCompetitorBriefTests(SimpleTestCase):
|
|||||||
"已售50万+",
|
"已售50万+",
|
||||||
)
|
)
|
||||||
self.assertEqual(infer_total_sales_from_sales_floor(""), "")
|
self.assertEqual(infer_total_sales_from_sales_floor(""), "")
|
||||||
|
|
||||||
|
def test_mix_top_remainder_sums_to_all_rows(self) -> None:
|
||||||
|
"""饼图与 §4 表同源:mix_top 各 count 之和须等于含名行数。"""
|
||||||
|
root = Path(settings.CRAWLER_JD_ROOT).resolve()
|
||||||
|
if str(root) not in sys.path:
|
||||||
|
sys.path.insert(0, str(root))
|
||||||
|
import jd_competitor_report as jcr # noqa: WPS433
|
||||||
|
|
||||||
|
names = [f"店{i}" for i in range(30)]
|
||||||
|
mix = jcr._counter_mix_top_rows_with_remainder(
|
||||||
|
names, top_n=24, remainder_label="(其余店铺)"
|
||||||
|
)
|
||||||
|
self.assertEqual(sum(v for _, v in mix), 30)
|
||||||
|
self.assertEqual(mix[-1][0], "(其余店铺)")
|
||||||
|
self.assertEqual(mix[-1][1], 6)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user