본문 바로가기

Javascript/Chart.js

ChatGPT로 Chart.js 알아보기 (10):혼합 차트(Mixed Chart Type)

반응형

ChatGPT로 Chart.js 알아보기 (10):혼합 차트(Mixed Chart Type)

이번 포스트에서는 ChatGPT에게 Chart.js로 혼합 차트(Mixed Chart type)를 생성하는 방법에 대해 가르쳐달라고 해보았다.
ChatGPT가 뽑아준 내용을 참고해서 공부해보았으며, 그 내용을 정리해보았다.

Mixed Chart Types란 하나의 그래프 안에 여러 타입의 차트를 섞어서 표현하는 것을 의미한다. 예를 들어, 한 축에는 막대그래프로, 다른 축에는 선그래프로 데이터를 표현하는 것이다.
이를 통해 복잡한 데이터도 효과적으로 시각화할 수 있다.
혼합 차트는 추가 설명없이 바로 예시를 보는 것이 좋을 것 같다.
혼합 차트 예시
혼합 차트를 생성하는 방법은 매우 간단하다.
Chart 객체에 data.datasets의 각 데이터에 type을 선언해주면 된다.
✔ 막대 & 꺾은 선 그래프 1
막대 그래프(Bar Chart)와 꺾은 선 그래프(Line Chart)를 함께 그려보았다.
data.datasets에 Line Chart로 생성할 데이터의 type을 line으로 주면 된다.
type: 'bar', // 기본적으로 설정되는 차트 타입 (여기서는 Bar chart)
data: {
    datasets: [{
        // ... Line chart로 그려줄 데이터
        type: 'line',
    }, {
        //... Bar chart로 그려줄 데이터
    }]
}
예시에서는 기본 차트는 Bar chart로 하고 Dataset 1의 차트 타입은 Line chart로 설정했다.
기본 차트를 Line chart로 하고 Dataset 2의 타입을 Bar chart로 해도 동일하게 제시된다.
아래는 위 차트의 전체 코드이다.
const mixedChart1 = document.querySelector('#mixedChart1').getContext('2d');

new Chart(mixedChart1, {
    type: 'bar',
    data: {
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        datasets: [{
            label: 'Dataset 1',
            type: 'line',
            borderColor: '#4BC0C0',
            data: [10, 20, 30, 40, 50, 60, 70],
            fill: false,
        }, {
            label: 'Dataset 2',
            backgroundColor: '#565656',
            data: [20, 30, 40, 50, 60, 70, 80],
        }]
    },
    options: {
        responsive: true,
        title: {
            display: true,
            text: 'Mixed Chart Types'
        },
    }
});
✔ 막대 & 꺾은 선 그래프 2
Bar chart와 Line chart를 혼합한 차트의 다른 예시를 한번 구현해 보았다.
사실 Mixed Chart Type에 대해 구글에서 이미지 검색을 해보다가 발견한 차트인데 이쁜 것 같아서 한번 만들어보았다.
1개의 Bar chart와 2개의 Line chart를 생성했으며, 각 Line chart는 다르게 옵션을 지정해주었다.
B에 해당되는 Line chart는 border를 4로, C에 해당되는 Line chart는 border를 1로하고 fill 옵션을 주었다.
그리고 borderWidth을 설정하게 되면 상단에 표시되는 legend에도 영향이 있기 때문에 options에 generateLabels를 변경해서 legend의 width는 1로 될 수 있게 변경해보았다.
아래는 위 차트의 전체 코드이다.
const mixedCtx2 = document.querySelector('#mixedChart2').getContext('2d');

new Chart(mixedCtx2, {
    type: 'bar',
    data: {
        labels: ['JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'],
        datasets: [
            {
                label: 'A',
                data: [20, 40, 10, 45, 20, 50],
                backgroundColor: 'rgb(28, 158, 247,1)',
            },
            {
                label: 'B',
                data: [40, 60, 20, 65, 50, 80],
                borderWidth: 4,
                borderColor: 'rgb(254, 176, 25, 1)',
                backgroundColor: 'rgb(254, 176, 25, 1)',
                type: 'line',
                tension: 0.4,
                pointRadius: 0,
            },
            {
                label: 'C',
                data: [60, 50, 50, 80, 40, 70],
                borderWidth: 1,
                borderColor: 'rgba(16, 163, 127, 1)',
                backgroundColor: 'rgba(16, 163, 127, 0.2)',
                fill: true,
                type: 'line',
                tension: 0.4,
                pointRadius: 0,
            }
        ]
    },
    options: {
        plugins: {
            legend: {
                labels: {
                    generateLabels: function(chart) {
                        const labels = Chart.defaults.plugins.legend.labels.generateLabels(chart);
                        labels.forEach(label => {
                            label.lineWidth = 1;
                        });

                        return labels;
                    },
                    boxWidth: 20,
                    padding: 20,
                    boxHeight: 20,
                }
            }
        }
    }
})
✔ 막대 & 꺾은 선 그래프 3
필자의 경우 Bar chart와 Line chart를 동시에 표시하는 차트하면 바로 생각나는 것이 바로 주식의 재무제표 차트이다.
재무제표에서 매출액, 영업이익, 당기순이익을 Bar chart로, 영업이익률, 당기순이익률을 Line chart로 그려주는 예시를 한번 살펴보겠다.
위 차트는 필자가 조만간 포스팅할 주식의 재무제표를 웹스크래핑해서 차트로 그리고 간단하게 분석을 하는 글에 사용할 차트 유형이다.
매출액, 영업이익, 당기순이익을 Bar chart로 그려주고, 영업이익률, 당기순이익률을 Line chart로 그려주었다.
그리고 금액 관련 y축은 '억원' 단위로 좌측에 표기되게 했으며, 이익률 관련 y축은 '%'로 우측에 표기되게 구현했다.
아래는 위 차트의 전체 코드이다.
const yearCtx = document.querySelector('#fs-y-chart').getContext('2d');
const yearChart = new Chart(yearCtx, {
    type: 'line',
    data: {
        labels: ['2020/12', '2021/12', '2022/12', '2023/12(E)'],
        datasets: [{
            label: '매출액',
            data: [242457, 262892, 300795, 307276],
            backgroundColor: 'rgba(16, 163, 127, 0.2)',
            borderColor: 'rgba(16, 163, 127, 1)',
            borderWidth: 1,
            yAxisID: 'y1',
            type: 'bar'
        }, {
            label: '영업이익',
            data: [13596, 15244, 16647, 14161],
            backgroundColor: 'rgba(0, 0, 128, 0.2)',
            borderColor: 'rgba(0, 0, 128, 1)',
            borderWidth: 1,
            yAxisID: 'y1',
            type: 'bar'
        }, {
            label: '당기순이익',
            data: [7864, 8924, 8027, 6375],
            backgroundColor: 'rgba(255, 99, 132, 0.2)',
            borderColor: 'rgba(255, 99, 132, 1)',
            borderWidth: 1,
            yAxisID: 'y1',
            type: 'bar'
        }, {
            label: '영업이익률',
            data: [5.61, 5.8, 5.53, 4.61],
            backgroundColor: 'rgba(255, 223, 0, 0.2)',
            borderColor: 'rgba(255, 223, 0, 1)',
            borderWidth: 2,
            yAxisID: 'y2',
        }, {
            label: '당기순이익률',
            data: [3.24, 3.39, 2.67, 2.07],
            backgroundColor: 'rgba(135, 206, 250, 0.2)',
            borderColor: 'rgba(135, 206, 250, 1)',
            borderWidth: 2,
            yAxisID: 'y2',
        }]
    },
    options: {
        scales: {
            y1: {
                position: 'left',
                ticks: {
                    callback: function(value, index, ticks) {
                        return `${value.toLocaleString()}억원`;
                    }
                }
            },
            y2: {
                beginAtZero: true,
                position: 'right',
                grid: {
                    drawOnChartArea: false,
                },
                ticks: {
                    callback: function(value, index, ticks) {
                        return `${value.toLocaleString()}%`;
                    }
                }
            }
        }
    }
});
위 코드에서도 확인할 수 있듯이, 기본 타입은 line이고 금액 관련 데이터에는 타입을 bar로 주었다.
그리고 y축을 선언해주는 yAxidID를 각 데이터에 선언해주었으며, options에서 scales에 y1, y2에 대한 옵션을 각각 설정해준 것을 확인할 수 있다.
✔ 막대 & 꺾은 선 & 산점도
막대 & 꺾은 선 그래프 말고도 산점도(Scatter)도 추가해볼 수 있다.
다만, 산점도를 추가할 때는 scatter 타입에 들어가는 data가 x, y로 작성되어야 한다.
그래서 사실 이런 방식을 할 때는 line chart의 옵션을 수정해주는게 더 편할 수 있다.
아래는 scatter 타입의 데이터를 추가해줄 때의 예시이다.
아래는 위 차트의 전체 코드이다.
const mixedChart3 = document.querySelector('#mixedChart3').getContext('2d');
new Chart(mixedChart3, {
    type: 'bar',
    data: {
        labels: ['January', 'February', 'March', 'April'],
        datasets: [{
            label: 'Bar Dataset',
            data: [10, 20, 30, 40],
            backgroundColor: 'rgba(255, 99, 132, 0.2)',
            borderColor: 'rgba(255, 99, 132, 1)',
        }, {
            label: 'Line Dataset',
            data: [20, 40, 25, 30],
            type: 'line',
            fill: false,
            borderColor: 'rgba(54, 162, 235, 1)',
            backgroundColor: 'rgba(54, 162, 235, 1)',
        }, {
            label: 'Scatter Dataset',
            data: [{
                x: -10,
                y: 0
            }, {
                x: 0,
                y: 10
            }, {
                x: 10,
                y: 5
            },{
                x: 20,
                y: 20
            }],
            type: 'scatter',
            backgroundColor: 'rgba(75, 192, 192, 1)',
            borderColor: 'rgba(75, 192, 192, 1)',
        }]
    },
    options: {
        scales: {
            y: {
                beginAtZero: true
            }
        }
    }
});
앞서 말했듯이 포인트 형태로 차트를 추가해주고 싶을 때는 scatter 타입을 사용하는 것 보다 line 타입을 사용하고 borderWidth를 0으로 두는 것이 더 좋다고 생각한다.
아래는 위 차트에서 생성한 line 차트의 borderWidth를 0으로 둬서 포인트 형태로 변경한 예시이다.
borderWidth를 0으로 설정해서 포인트로 표시되게 변경했다.
위 line 차트 데이터에 borderWidth 설정만 추가해주면 된다.
{
    label: 'Line Dataset(point)',
    data: [20, 40, 25, 30],
    type: 'line',
    fill: false,
    borderColor: 'rgba(54, 162, 235, 1)',
    backgroundColor: 'rgba(54, 162, 235, 1)',
    borderWidth: 0 // 포인트 형태로 변경
}
✔ 산점도 & 선형회귀선
이전 포스트에 작성한 산점도 글에도 작성한 것이지만 산점도에 line 차트를 추가하는 것을 활용해서 선형회귀선을 구현해볼 수도 있다.
아래는 위의 차트를 구현할 때 사용한 코드이다.
const regresstionCtx = document.querySelector('#regresstionChart').getContext('2d');
const regresstionChart = new Chart(regresstionCtx, {
    type: 'scatter',
    data: {
        datasets: [{
            label: '실제값',
            data: regresstionData,
            backgroundColor: 'rgb(16, 163, 127, 0.5)',
            borderColor: 'rgb(16, 163, 127, 1)',
            pointRadius: 5
        },
        {
            label: '선형회귀선',
            data: regresstionLRData,
            type: 'line',
            borderColor: 'rgb(89, 89, 89, 1)',
            backgroundColor: 'rgb(89, 89, 89, 1)',
            pointRadius: 0,
        }]
    },
    options: {
        scales: {
            x: {
                max: 80
            }
        }
    }
});
실제값을 기준으로 regresstionLRData를 계산해서 선형회귀선을 그릴 데이터를 추가해주었다.
그리고 pointRadius를 0으로 줘서 포인트가 보이지 않게 설정했다.
이번에는 Chart.js로 혼합 차트(Mixed Chart Type)에 대해서 알아보는 시간을 가졌다.
Chart.js의 기본적인 내용은 거진 다 공부해 본 것 같다.
다음은 다양한 plugin들을 알아봐야 하는데... 생각보다 분량이 많을 것 같아서 겁난다.

아무튼 Chart.js 글들을 작성하면서 개인적으로도 많은 공부가 됐다.
처음 Chart.js를 접했을 때는 JavaScript도 잘 모르던 때 건드린 거라 뭔가 어려웠는데 막상 지금 공부를 해보니 왜 쉽다고 한 건지 알 것 같다.
ChatGPT로 공부하는게 확실히 도움이 많이 되고 편하다는 것도 이번 포스트들을 작성하면서 다시 한번 느끼게 되었다.
다음은 무엇을 공부해 볼지 고민해 봐야겠다.
커피 한 잔으로
저를 응원해주세요!
반응형

loading