File size: 1,794 Bytes
a1aef88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import Plot from 'react-plotly.js';
import type { CramersVData } from '../../types';

interface Props {
  data: CramersVData;
  height?: number;
}

export function CorrelationHeatmap({ data, height = 400 }: Props) {
  // Mask upper triangle
  const masked = data.matrix.map((row, i) =>
    row.map((val, j) => (j > i ? null : val))
  );

  // Annotation text
  const annotations = [];
  for (let i = 0; i < data.labels.length; i++) {
    for (let j = 0; j <= i; j++) {
      annotations.push({
        x: data.labels[j],
        y: data.labels[i],
        text: masked[i][j] != null ? masked[i][j]!.toFixed(2) : '',
        font: { color: '#e6edf3', size: 10 },
        showarrow: false,
      });
    }
  }

  return (
    <Plot
      data={[
        {
          z: masked,
          x: data.labels,
          y: data.labels,
          type: 'heatmap',
          colorscale: [
            [0, '#0d1117'],
            [0.25, '#1f3a5f'],
            [0.5, '#3d6098'],
            [0.75, '#d29922'],
            [1, '#f85149'],
          ],
          zmin: 0,
          zmax: 1,
          hoverongaps: false,
          colorbar: {
            title: { text: "Cramer's V", font: { color: '#8b949e', size: 10 } },
            tickfont: { color: '#8b949e', size: 9 },
          },
        },
      ]}
      layout={{
        title: {
          text: "Cramer's V Correlation Matrix",
          font: { color: '#e6edf3', size: 14 },
        },
        paper_bgcolor: 'transparent',
        plot_bgcolor: 'transparent',
        font: { color: '#8b949e', size: 10 },
        margin: { l: 100, r: 40, t: 40, b: 100 },
        xaxis: { tickangle: -45 },
        annotations,
        height,
      }}
      config={{ responsive: true, displayModeBar: false }}
      style={{ width: '100%' }}
    />
  );
}