---
code: "DIS-15"
id: "c-ridge"
tab: "distribution"
kind: "core"
title: "Ridgeline · 능선 분포"
library: "SVG"
deps: ["svg"]
load: "low"
pasteKind: "custom-mount"
family: "distribution"
dataShape: "many group density curves stacked as ridges"
tasks: ["show composition", "show frequency", "compare magnitudes", "compare distribution shapes across groups"]
tags: ["distribution", "비율", "빈도", "ridgeline", "joy plot", "능선", "분포"]
gallery: "https://graph.heal7.com/#DIS-15"
js: "/sku/DIS-15.js"
---

# [DIS-15] Ridgeline · 능선 분포

> AI 붙여넣기 카드. 갤러리 런타임(`main.js`)이 아니라 이 파일을 가져와라.

## 언제 가져가나
그룹마다 밀도 곡선을 한 층씩 쌓아 봉우리·꼬리를 겹치지 않고 비교 — 오버레이 밀도와 다른 과업.

**응용** 직무별 점수 분포, 모델별 오차 분포, 연령대별 응답 시간.

## 데이터 모양
- family: `distribution`
- dataShape: many group density curves stacked as ridges
- tasks: show composition, show frequency, compare magnitudes, compare distribution shapes across groups
- tags: distribution, 비율, 빈도, ridgeline, joy plot, 능선, 분포


## 의존
svg · load `low` · library `SVG`

## 붙여넣는 법
1. 라이브러리 없이 host 엘리먼트에 직접 그린다
2. 함수 전체를 가져간다
3. `getElementById('원본id')` 만 대상 노드로 바꾼다

```js
const T = {
  "bg": "transparent",
  "fg": "#ece8f5",
  "sub": "#a59bbd",
  "grid": "rgba(255,255,255,.08)",
  "gold": "#e8c069",
  "royal": "#6b8cff",
  "rose": "#e07a9f",
  "teal": "#6dd2c4",
  "plum": "#b487e8"
};
const isDark = () => document.documentElement.getAttribute('data-theme') !== 'light';
const host = document.querySelector('#chart');
const factory = function(){
  const host = document.getElementById('c-ridge'); if(!host) return;
  const groups = [
    {n:'기획', mu:58, s:9, c:T.gold},
    {n:'디자인', mu:71, s:7, c:T.plum},
    {n:'개발', mu:66, s:11, c:T.royal},
    {n:'마케팅', mu:62, s:10, c:T.rose},
    {n:'영업', mu:74, s:8, c:T.teal},
    {n:'CS', mu:54, s:12, c:'#9aa0a6'}
  ];
  const k = (x, mu, s) => Math.exp(-((x-mu)*(x-mu))/(2*s*s));
  const left=56, right=390, top=18, rowH=34;
  const xOf = v => left + (v-20)/80*(right-left);
  const rows = groups.map((g, gi) => {
    const base = top + 16 + gi*rowH;
    let d = `M ${xOf(20)} ${base}`;
    for(let x=20;x<=100;x+=2) d += ` L ${xOf(x).toFixed(1)} ${(base - k(x,g.mu,g.s)*28).toFixed(1)}`;
    d += ` L ${xOf(100)} ${base} Z`;
    return `<text x="8" y="${base-2}" fill="${T.fg}" font-size="11" font-weight="600">${g.n}</text>
      <path d="${d}" fill="${g.c}" fill-opacity="0.28" stroke="${g.c}" stroke-width="1.6"/>
      <line x1="${left}" y1="${base}" x2="${right}" y2="${base}" stroke="${T.grid}" stroke-width="1"/>`;
  }).join('');
  host.innerHTML = `<svg viewBox="0 0 400 240" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
    ${rows}
    <text x="${xOf(20)}" y="232" fill="${T.sub}" font-size="10">20</text>
    <text x="${xOf(60)}" y="232" fill="${T.sub}" font-size="10" text-anchor="middle">60</text>
    <text x="${xOf(100)}" y="232" fill="${T.sub}" font-size="10" text-anchor="end">100</text>
  </svg>`;
};
factory();
```

## 원본 factory (갤러리 정본 발췌)
- file: `frontend/js/graph-gallery/main.js`
- lines: 3172-3200
- gallery: https://graph.heal7.com/#DIS-15
- raw js: https://graph.heal7.com/sku/DIS-15.js

```js
function(){
  const host = document.getElementById('c-ridge'); if(!host) return;
  const groups = [
    {n:'기획', mu:58, s:9, c:T.gold},
    {n:'디자인', mu:71, s:7, c:T.plum},
    {n:'개발', mu:66, s:11, c:T.royal},
    {n:'마케팅', mu:62, s:10, c:T.rose},
    {n:'영업', mu:74, s:8, c:T.teal},
    {n:'CS', mu:54, s:12, c:'#9aa0a6'}
  ];
  const k = (x, mu, s) => Math.exp(-((x-mu)*(x-mu))/(2*s*s));
  const left=56, right=390, top=18, rowH=34;
  const xOf = v => left + (v-20)/80*(right-left);
  const rows = groups.map((g, gi) => {
    const base = top + 16 + gi*rowH;
    let d = `M ${xOf(20)} ${base}`;
    for(let x=20;x<=100;x+=2) d += ` L ${xOf(x).toFixed(1)} ${(base - k(x,g.mu,g.s)*28).toFixed(1)}`;
    d += ` L ${xOf(100)} ${base} Z`;
    return `<text x="8" y="${base-2}" fill="${T.fg}" font-size="11" font-weight="600">${g.n}</text>
      <path d="${d}" fill="${g.c}" fill-opacity="0.28" stroke="${g.c}" stroke-width="1.6"/>
      <line x1="${left}" y1="${base}" x2="${right}" y2="${base}" stroke="${T.grid}" stroke-width="1"/>`;
  }).join('');
  host.innerHTML = `<svg viewBox="0 0 400 240" width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
    ${rows}
    <text x="${xOf(20)}" y="232" fill="${T.sub}" font-size="10">20</text>
    <text x="${xOf(60)}" y="232" fill="${T.sub}" font-size="10" text-anchor="middle">60</text>
    <text x="${xOf(100)}" y="232" fill="${T.sub}" font-size="10" text-anchor="end">100</text>
  </svg>`;
}
```

