Histogram

Data Visualization

visx 기반 히스토그램.

Usage

연속 수치가 구간별로 얼마나 분포하는지 빈도로 확인할 때 사용한다.

import

import

import { Histogram } from '@mildang/design-system/Chart';

예제를 복사해 쓸 때 필요한 준비

@mildang/styled-system 은 이 저장소에서 Panda 가 생성하는 산출물이다. 저장소 안에서는 turbo run ship 이후 쓸 수 있고, 패키지 소비자는 자기 Panda 산출물이나 다른 레이아웃 수단으로 바꿔야 한다.

API Reference

Histogram Props

Prop

Type

Default

data
필수

TDatum[]

지정 안 함

valueKey
필수

string

지정 안 함

binCount

number

지정 안 함

className

string

지정 안 함

color

string

지정 안 함

formatValue

(value: number) => string

(value: number) => value.toLocaleString()

label

string

빈도

legendPosition

"bottom" | "left" | "right" | "top"

bottom

margin

Partial<ChartMargin>

지정 안 함

showGrid

boolean

true

showLegend

boolean

false

showTooltip

boolean

false

showXAxis

boolean

true

showYAxis

boolean

true

예제

기본 (Sturges 구간)

import { Histogram } from '@mildang/design-system/Chart';

// 학생 32명의 영어 시험 점수 — 32개(Sturges 6구간), 최소 40 · 최대 100이라 경계가 10점 단위로 떨어진다
const scoreData = [
  { student: '학생1', score: 40 },
  { student: '학생2', score: 45 },
  { student: '학생3', score: 52 },
  { student: '학생4', score: 55 },
  { student: '학생5', score: 58 },
  { student: '학생6', score: 61 },
  { student: '학생7', score: 63 },
  { student: '학생8', score: 65 },
  { student: '학생9', score: 67 },
  { student: '학생10', score: 68 },
  { student: '학생11', score: 70 },
  { student: '학생12', score: 71 },
  { student: '학생13', score: 72 },
  { student: '학생14', score: 73 },
  { student: '학생15', score: 74 },
  { student: '학생16', score: 75 },
  { student: '학생17', score: 76 },
  { student: '학생18', score: 77 },
  { student: '학생19', score: 78 },
  { student: '학생20', score: 79 },
  { student: '학생21', score: 81 },
  { student: '학생22', score: 82 },
  { student: '학생23', score: 84 },
  { student: '학생24', score: 85 },
  { student: '학생25', score: 87 },
  { student: '학생26', score: 88 },
  { student: '학생27', score: 90 },
  { student: '학생28', score: 92 },
  { student: '학생29', score: 94 },
  { student: '학생30', score: 96 },
  { student: '학생31', score: 98 },
  { student: '학생32', score: 100 },
];

const HistogramDefaultExample = () => <Histogram data={scoreData} valueKey="score" />;

export default HistogramDefaultExample;

구간 개수 지정

import { Histogram } from '@mildang/design-system/Chart';

// 학생 32명의 영어 시험 점수 — 32개(Sturges 6구간), 최소 40 · 최대 100이라 경계가 10점 단위로 떨어진다
const scoreData = [
  { student: '학생1', score: 40 },
  { student: '학생2', score: 45 },
  { student: '학생3', score: 52 },
  { student: '학생4', score: 55 },
  { student: '학생5', score: 58 },
  { student: '학생6', score: 61 },
  { student: '학생7', score: 63 },
  { student: '학생8', score: 65 },
  { student: '학생9', score: 67 },
  { student: '학생10', score: 68 },
  { student: '학생11', score: 70 },
  { student: '학생12', score: 71 },
  { student: '학생13', score: 72 },
  { student: '학생14', score: 73 },
  { student: '학생15', score: 74 },
  { student: '학생16', score: 75 },
  { student: '학생17', score: 76 },
  { student: '학생18', score: 77 },
  { student: '학생19', score: 78 },
  { student: '학생20', score: 79 },
  { student: '학생21', score: 81 },
  { student: '학생22', score: 82 },
  { student: '학생23', score: 84 },
  { student: '학생24', score: 85 },
  { student: '학생25', score: 87 },
  { student: '학생26', score: 88 },
  { student: '학생27', score: 90 },
  { student: '학생28', score: 92 },
  { student: '학생29', score: 94 },
  { student: '학생30', score: 96 },
  { student: '학생31', score: 98 },
  { student: '학생32', score: 100 },
];

const HistogramCustomBinCountExample = () => <Histogram data={scoreData} valueKey="score" binCount={12} />;

export default HistogramCustomBinCountExample;

커스텀 색상 · 값 포맷 · 범례

import { Histogram } from '@mildang/design-system/Chart';
import { token } from '@mildang/styled-system/tokens';

// 학생 32명의 영어 시험 점수 — 32개(Sturges 6구간), 최소 40 · 최대 100이라 경계가 10점 단위로 떨어진다
const scoreData = [
  { student: '학생1', score: 40 },
  { student: '학생2', score: 45 },
  { student: '학생3', score: 52 },
  { student: '학생4', score: 55 },
  { student: '학생5', score: 58 },
  { student: '학생6', score: 61 },
  { student: '학생7', score: 63 },
  { student: '학생8', score: 65 },
  { student: '학생9', score: 67 },
  { student: '학생10', score: 68 },
  { student: '학생11', score: 70 },
  { student: '학생12', score: 71 },
  { student: '학생13', score: 72 },
  { student: '학생14', score: 73 },
  { student: '학생15', score: 74 },
  { student: '학생16', score: 75 },
  { student: '학생17', score: 76 },
  { student: '학생18', score: 77 },
  { student: '학생19', score: 78 },
  { student: '학생20', score: 79 },
  { student: '학생21', score: 81 },
  { student: '학생22', score: 82 },
  { student: '학생23', score: 84 },
  { student: '학생24', score: 85 },
  { student: '학생25', score: 87 },
  { student: '학생26', score: 88 },
  { student: '학생27', score: 90 },
  { student: '학생28', score: 92 },
  { student: '학생29', score: 94 },
  { student: '학생30', score: 96 },
  { student: '학생31', score: 98 },
  { student: '학생32', score: 100 },
];

const HistogramCustomColorAndFormatExample = () => (
    <Histogram
      data={scoreData}
      valueKey="score"
      color={token('colors.blue.light.400')}
      formatValue={(v) => `${v}점`}
      label="학생 수"
      showLegend
    />
  );

export default HistogramCustomColorAndFormatExample;

Hover Tooltip

import { Histogram } from '@mildang/design-system/Chart';

// 툴팁 테스트용 — 60~100 · 4구간이라 경계가 정확히 60/70/80/90/100.
// 첫 구간 빈도 5는 y축 눈금(0,2,4,…,12)과 겹치지 않아 findByText가 유일하게 매칭된다
const tooltipData = [
  { minutes: 60 }, { minutes: 62 }, { minutes: 64 }, { minutes: 66 }, { minutes: 68 },
  { minutes: 70 }, { minutes: 71 }, { minutes: 72 }, { minutes: 73 }, { minutes: 74 },
  { minutes: 75 }, { minutes: 76 }, { minutes: 77 }, { minutes: 78 }, { minutes: 79 },
  { minutes: 79 }, { minutes: 79 },
  { minutes: 81 }, { minutes: 82 }, { minutes: 84 }, { minutes: 85 }, { minutes: 86 },
  { minutes: 87 }, { minutes: 88 }, { minutes: 89 },
  { minutes: 90 }, { minutes: 92 }, { minutes: 94 }, { minutes: 96 }, { minutes: 98 },
  { minutes: 100 },
];

const HistogramHoverTooltipExample = () => (
    <Histogram data={tooltipData} valueKey="minutes" binCount={4} label="빈도" showTooltip />
  );

export default HistogramHoverTooltipExample;

빈 데이터

import { Histogram } from '@mildang/design-system/Chart';

const HistogramEmptyExample = () => <Histogram data={[] as { score: number }[]} valueKey="score" />;

export default HistogramEmptyExample;

데이터 1개 (단일 값)

import { Histogram } from '@mildang/design-system/Chart';

const HistogramSingleValueExample = () => <Histogram data={[{ score: 85 }]} valueKey="score" showTooltip />;

export default HistogramSingleValueExample;

반응형 (너비 자동 조정)

import { Histogram } from '@mildang/design-system/Chart';

// 학생 32명의 영어 시험 점수 — 32개(Sturges 6구간), 최소 40 · 최대 100이라 경계가 10점 단위로 떨어진다
const scoreData = [
  { student: '학생1', score: 40 },
  { student: '학생2', score: 45 },
  { student: '학생3', score: 52 },
  { student: '학생4', score: 55 },
  { student: '학생5', score: 58 },
  { student: '학생6', score: 61 },
  { student: '학생7', score: 63 },
  { student: '학생8', score: 65 },
  { student: '학생9', score: 67 },
  { student: '학생10', score: 68 },
  { student: '학생11', score: 70 },
  { student: '학생12', score: 71 },
  { student: '학생13', score: 72 },
  { student: '학생14', score: 73 },
  { student: '학생15', score: 74 },
  { student: '학생16', score: 75 },
  { student: '학생17', score: 76 },
  { student: '학생18', score: 77 },
  { student: '학생19', score: 78 },
  { student: '학생20', score: 79 },
  { student: '학생21', score: 81 },
  { student: '학생22', score: 82 },
  { student: '학생23', score: 84 },
  { student: '학생24', score: 85 },
  { student: '학생25', score: 87 },
  { student: '학생26', score: 88 },
  { student: '학생27', score: 90 },
  { student: '학생28', score: 92 },
  { student: '학생29', score: 94 },
  { student: '학생30', score: 96 },
  { student: '학생31', score: 98 },
  { student: '학생32', score: 100 },
];

const HistogramResponsiveExample = () => (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 32, width: '100%' }}>
      {([280, 480, 720] as const).map((w) => (
        <div key={w} style={{ width: w }}>
          <div style={{ marginBottom: 4, fontSize: 11, color: '#888' }}>{w}px</div>
          <div style={{ width: w, height: 240 }}>
            <Histogram data={scoreData} valueKey="score" />
          </div>
        </div>
      ))}
    </div>
  );

export default HistogramResponsiveExample;