min117の日記

初期desireもち。趣味Mac,メインFedora,仕事xp。

JavaScriptで職業別求人・求職バランスシートをグラフ化 → プルダウンで有効求人倍率の折れ線グラフを更新する

ハピタス登録で1,000円分になるURL

その買うを、もっとハッピーに。|ハピタス

 

こないだからやってる過疎地域の雇用データ(有効求人倍率)のグラフ化

min117.hatenablog.com

Pythonで描いたグラフを

JavaScriptでグラフにしてみる

できた。

 

だいぶ印象違うなぁ。JavaScriptは何か軽い感じ。PythonBloombergっぽい。数字がプロットされてて良い。

 

追加実装したいところ

・グラフに数字をつける。棒グラフにも折れ線にも、その数値(項目ラベル)をプロットしたい。

・左軸に「人数」、右軸に「有効求人倍率」の見出しを付ける。

・プルダウンで選ぶCSVファイルを(ソースに直書きじゃなくて)サーバにあるCSV正規表現で読み込んで表示するようにしたい。

・棒グラフを積み上げグラフにする。一般有効求人倍率(正規社員)と、パート有効求人倍率(非正規)で積み上げたい。

・æ£<92>グラフが天井についたら、その天井に数字を表示したい。

・左(Y軸)のMAXを150人で固定したい。レンジが大きすぎると他の小さい数字の差異がパッと見で分からなくなっちゃうから。

 

qiita.com

wordpress.kazunoriri.com

 

 

今回もChatGPTが大活躍

csvデータを読み込んでChartJSでグラフ化するjavascriptのコードを示して。プルダウンで読み込むデータを選択できるようにして

 

ChartJSで、棒グラフそれぞれに、その高さ(項目ラベル)を表示する方法を教えて

数値が表示されません。display:trueなどを入れる必要があるのでは?

 

プルダウンで項目を選んだそのタイミングで関数を呼ぶjavascriptのコードを示して/ChartJSで、最初にそのページが開かれた時に表示されるグラフと、そのあとプルダウンで選ばれた時に表示されるグラフを切り替えるにはどうすればいい?

htmlが最初に読み込まれた1回だけ実行されるJavascriptの関数はどのように書けばいいの?

Chart.jsのpluginsで項目ラベルを表示する設定したくて以下の記述(抜粋)したけど、なぜか項目ラベルが表示されません。直し方は分かりますか?

 

Chartjsのバージョン3以降で、項目ラベルを表示するためのpluginsの記述についてシンプルな例を示して/項目ラベルが表示されません

 

chartjsのversion3で折れ線グラフに数値をプロットしたい

もうGoogleいらんな。巷にあふれるしょうもないサイト(現役エンジニアが解説!みたいな)よりChatGPTのほうが遥かに役に立つ

 

今回のソースコード

132行目 プルダウンで選択したときにすでに格納されてるインスタンスmyChartをちゃんと.destroyしないとマウス重ねるたびにグラフが(サブリミナル画像みたいに)入れ変わっちゃうような変な動作をする。

 

qiita.com

wordpress.kazunoriri.com

 

.destroy()メソッドについて

 

<HTML>
<HEAD>
<style>
.box select{
/* width: 100px;
width: 500px; 
height: 50px */
border: 1px solid;
font-size: 30px;
}
</style>


<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script>


<div style="width:100%">
    <canvas id="canvas"></canvas>
</div>

<!--
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js">
<script src="https://unpkg.com/chart.js-plugin-labels-dv@3.0.5/dist/chartjs-plugin-labels.min.js"</script>
<div class="box">
<select onchange="set_img(this.selectedIndex)">
    <script language=javascript>
        for(nn=0;nn<list_csvv.length;nn++) {
            // document.write("<option>" + list_csvv[nn][1]);
            document.write("<option>" + list_csvv[nn]);
        }
    </script>
</select>
</div>
-->


<hr>
<div class="box" align="center">
<!-- <select id="csv-select"> -->
<select id="csv-select" onchange="myFunction()">

    <!--
    <option value="sample2.csv">sample2.csv</option>
    <option value="sample3.csv">sample3.csv</option>
    <option value="202210_001367794_うちI>T関連職業.csv">202210_001367794_うちIT関連職業</option>
    <option value="202211_001367794_うちIT関連職業.csv">202211_001367794_うちIT関連職業</option>
    <option value="202212_001367794_うちIT関連職業.csv">202212_001367794_うちIT関連職業</option>
    -->
    <option value="202201_001102759_うちIT関連職業.csv">202201</option>
    <option value="202202_001120375_うちIT関連職業.csv">202202</option>

    <option value="202203_001139041_うちIT関連職業.csv">202203</option>
    <option value="202204_001162568_うちIT関連職業.csv">202204</option>
    <option value="202205_001188058_うちIT関連職業.csv">202205</option>
    <option value="202206_001209322_うちIT関連職業.csv">202206</option>
    <option value="202207_001233778_うちI T関連職業.csv">202207</option>
    <option value="202208_001260287_うちIT関連職業.csv">202208</option>
    <option value="202209_001284855_うちIT関連職業.csv">202209</option>
    <option value="202210_001312912_うちIT関連職業.csv">202210</option>
    <option value="202211_001338172_うちIT関連職業.csv">202211</option>
    <option value="202212_001367794_うちIT関連職業.csv">202212</option>
</select>
<!--
<button id="load-csv-button">Load CSV</button>
-->
</div>
<a href="https://wordpress.kazunoriri.com/https-kazunoriri-com-wordpress-chart-js-bar-csv/" target="_blank">WordPress | CSVを読み込んでChart.jsの棒グラフを描画する方法</a>
<br />
<a href="https://qiita.com/saka212/items/5714fa68deb44a185ec3">Chart.jsでグラフを更新するサン
プル(ボタンをクリック)</a>
<!--
キャラ,HP,MP,ちから,すばやさ
ヨ シヒコ,330,200,150,90
アリーナ,300,0,200,220
マーニャ,230,300,40,130j
ミネア,240,170,80,80

koumoku,YEARMM,JOBB,求人数,求職者数,求人倍率,一般求人数,一般求職者数,一般求人倍率,パート求人>数,パート求職者数,パート求人倍率
秋田労働局,202212,うちIT関連職業,497,433,1.15,435,357,1.22,62,76,0.82
秋田,202212,うちIT関連職業,172,175,0.98,153,138,1.11,19,37,0.51
男鹿,202212,うちIT関連職業,7,9,0.78,2,6,0.33,5,3,1.67
能代,202212,うちIT関連職業,49,17,2.88,49,15,3.27,0,2,0
大館 ,202212,うちIT関連職業,46,20,2.30,43,14,3.07,3,6,0.50
鷹巣,202212,うちIT関連職業,6,9,0.67,6,8,0.75,0,1,0
大曲,202212,うちIT関連職業,41,23,1.78,33,18,1.83,8,5,1.60
角館,202212,うちIï¼´>関連職業,9,9,1.00,5,8,0.63,4,1,4.00
本荘,202212,うちIT関連職業,60,107,0.56,55,101,0.54,5,6,0.83
横手,202212,うちIT関連職業,57,24,2.38,39,17,2.29,18,7,2.57
湯沢,202212,うちIT関連職業,30,31,0.97,30,25,1.20,0,6,0
鹿角,202212,うちIT関連職業,20,9,2.22,20,7,2.86,0,2,0
-->

<script>
//const list_csvv = ;
////for (let i = 1; i<=12; i++){
//for (let j = 2019; j<=2022; j++) {
//    for (let i = 1; i<=12; i++){
//        console.log(i);
//        if(i < 10 ) {
//            const filename1 = `myKINRIROUKI03_24うちIT関連職業_00全体_${j}0${i}.csv`;
//            list_csvv.push(filename1);
//        } else {
//            const filename1 = `myKINRIROUKI03_24うちIT関連職業_00全体_${j}${i}.csv`;
//            list_csvv.push(filename1);

//        }
//    }
//}


const csvSelect = document.getElementById("csv-select");
// const loadCsvButton = document.getElementById("load-csv-button");
// const chartCanvas = document.getElementById("chart");
let chart = null;

// loadCsvButton.addEventListener("click", () => {
//       const selectedCsv = csvSelect.value;
//       console.log(selectedCsv);
//       loadCsv(selectedCsv);
// });

// window.onload = function() {
// window.onload = loadCsv('sample2.csv');
window.onload = loadCsv('sample3.csv');
// document.addEventListener("DOMContentLoaded", function() {
//     // ここに実行したい関数のコードを記述する
//     console.log("This function will run only once when the HTML page is loaded.");
//     loadCsv('sample2.csv');
// });


function myFunction() {
    const selectedValue = document.getElementById('csv-select').value;
    if(myChart) {
        myChart.destroy();
    }
    loadCsv(selectedValue);
}

 

function loadCsv(CSVV) {
    // let キャラ = ;
    // let HPのデータ = ;
    // let MPのデータ =
;
    // let ちからのデータ = ;
    // let すばやさのデータ =
;
    let col_koumoku = ;
    let col_YEARMM =
;
    let col_JOBB = ;
    let col_KYUJINSU =
;
    let col_KYUSYOKU = ;
    let col_KYUJINRITU =
;
    let col_I_KYUJINSU = ;
    let col_I_KYUSYOKU =
;
    let col_I_KYUJINRITU = ;
    let col_P_KYUJINSU =
;
    let col_P_KYUSYOKU = ;
    let col_P_KYUJINRITU =
;


    // let csvPath = './sample1.csv'
    // let csvPath = './sample2.csv';
    let csvPath = CSVV;

    // リクエストreqの定義 オブジェクトの本体req
    let req = new XMLHttpRequest();
    req.open('get', csvPath, true);                                       // 1
    req.send(null);
    req.onload = function() {                                             // 2
        makeGraphData();
        drawGraph();

        function makeGraphData() {
            // まずは改行で分ける
            let reqArray = req.responseText.split('\n');                      // 3
            // reqArrayには
            // ヘッダデータ
            // 秋田,202212,うちIT関連職業,172,175,0.98,153,138,1.11,19,37,0.51
            // 男鹿,202212,うちIT関連職業,7,9,0.78,2,6,0.33,5,3,1.67
            // ...
            // 末尾まで が全部格納される
            
            reqArray.forEach*1;
                };
                if(ROWW_DATA[indexKYUSYOKU] !== undefined) {
                    col_KYUSYOKU.push(Number(ROWW_DATA[indexKYUSYOKU]));
                };
                if(ROWW_DATA[indexKYUJINRITU] !== undefined) {
                    col_KYUJINRITU.push(Number(ROWW_DATA[indexKYUJINRITU]));
                };
            });
            removeHeader()


            function removeHeader() {
                col_koumoku.shift();
                col_KYUJINSU.shift();
                col_KYUSYOKU.shift();
                col_KYUJINRITU.shift();
                // キャラ.shift();
                // HPのデータ.shift();
                // MPのデータ.shift();
                // ちからのデータ.shift();
                // すばやさのデータ.shift();
            };
        };

        function drawGraph() {
            let ctx = document.getElementById('canvas').getContext('2d');
            // let グラフ = new Chart(ctx, {
            // myGraph
            // var myG = new Chart(ctx, {
            // optionsドロップダウン選択時にmyChart.destroy必須
            window.myChart = new Chart(ctx, {
                type: 'bar',    // ここはbarのま>まにする2軸でも
                data: G_DATA,
                options: G_OPTION2
                // data: グラフのデータ,
                // options: グラフのオプション
                // options: G_OPTION
            });
        };

    };

    // var グラフのデータ = {
    var G_DATA = {
        // labels: キャラ,
        // ↓このlabelsでX軸の単位(秋田,男鹿,能代...)が描画される
        labels: col_koumoku,
        datasets: [
            // {
            //     //label: 'HP',
            //     label: 'col_koumoku',
            //     // data: HPのデータ,
            //     data: col_koumoku,
            //     borderColor     : "rgba(55,155,255,0.7)",
            //     backgroundColor : "rgba(55,155,255,0.5)",
            // },
            {
                type: 'bar',
                label: '求人数',
                // label: 'col_KYUJINSU',
                data: col_KYUJINSU,
                borderColor     : "rgba(0,0,255,0.7)",
                backgroundColor : "rgba(0,0,255,0.5)",
                // borderColor     : "rgba(255,100,133,0.7)",
                // backgroundColor : "rgba(255,100,133,0.5)",

                // 左軸に表示
                yAxisID: "y1",
                // yAxisID: "y-axis-1",
            },
            {
                type: 'bar',
                label: '求職者数',
                data: col_KYUSYOKU,
                borderColor     : "rgba(255,0,0,0.7)",
                backgroundColor : "rgba(255,0,0,0.5)",
                // borderColor     : "rgba(55,255,55,0.7)",
                // backgroundColor : "rgba(55,255,55,0.5)",
                yAxisID: "y1",
            },
            {
                type: 'line',
                label: '求人倍率(右軸)',
                data: col_KYUJINRITU,
                borderColor     : "rgba(0,0,255,0.3)",
                // borderColor     : "rgba(255,222,133,0.7)",
                //backgroundColor : "rgba(255,222,133,0.3)",
                backgroundColor     : "rgba(0,0,255,0.3)",
                tension: 0, //0なら直線、0.1以上は>曲線
                fill: false, //直線からX軸までの範囲を塗りつぶすならtrue
                // 右軸に表示
                yAxisID: "y2",
                pointRadius: 5,
                pointHoverRadius: 7,
                pointBackgroundColor: 'white',
                pointBorderColor: 'rgb(75, 192, 192)',
                pointHoverBackgroundColor: 'rgb(75, 192, 192)',
                pointHoverBorderColor: 'white',
            },
        ],
    };

    // const G_OPTION2 = {
    // Chart.jsのVer2→3でyAxesの書き方が大きく変わった
    var G_OPTION2 = {
        // responsive: true,
        plugins: {
            title:{
                display: true,
                text: '職業別求人・求職バランスシート',
            },
            labels: {
                display: true
            },
            datalabels: {
                anchor: 'end',
                align: 'top',
                font: {
                    weight: 'bold'
                },
                // formatter: function(value) {

                //     return value;
                // }
                formatter: function(value, context) {
                    // return context.chart.data.labels[context.dataIndex];
                    return value;
                },
            },
        },
        scales: {
            y1: {
                type: "linear",
                position: "left",
                display: true,
                // id: "y-axis-1",
                ticks: {
                    callback: function(value){
                        return value+'人';
                    },
                    suggestedMax: "300",
                    suggestedMin: "0",
                    stepSize: 100,
                    //beginAtZero: true,
                    // max: 150,
                    // max: 300,
                    // min: 0,
                },
                scaleLabel: {
                    display: true,
                    // labelString: 'あたい'
                    labelString: '人数'
                }
            },
            y2: {
                type: "linear",
                position: "right",
                display: true,
                // id: "y-axis-1",
                ticks: {
                    callback: function(value){
                        return value+'%';
                    },
                    max: "4",
                    min: "0",
                    stepSize: 1,
                    //beginAtZero: true,
                    // max: 150,
                    // max: 300,
                    // min: 0,
                },
                scaleLabel: {
                    display: true,
                    labelString: '有効求人倍率'
                },
                grid: {
                    drawOnChartArea: false,

                },
            },
            // y2:{
            //     // 右軸
            //     id: "y-axis-2",
            //     // type: "linear",
            //     // 右を指定
            //     position: "right",
            //     // 目盛り
            //     ticks: {
            //         beginAtZero: true,
            //         max: 4,
            //         min: 0,
            //         stepsize: 1
            //     },
            //     // Y軸の目盛り(軸ラベル)
            //     scaleLabel: {
            //         display: true,
            //         // labelString: 'あたい'
            //         labelString: '有効求人倍率'
            //     },
            //     gridLines: {
            //         display: false
            //     },
            // }  // y -----
        }
    };
};

</script>

</HEAD>
</div>

<br><br>
</center>
</BODY>
</HTML>

 

 

 

 

 

 

その買うを、もっとハッピーに。|ハピタス

 

*1:element) => {                                   // 4
                //  ROWW_DATA 行データ
                let ROWW_DATA = element.split(',')
                let indexYEARMM = reqArray[0].split(',').indexOf('YEARMM');
                let indexJOBB = reqArray[0].split(',').indexOf('JOBB');

                let indexKYUJINSU = reqArray[0].split(',').indexOf('求人数');
                let indexKYUSYOKU = reqArray[0].split(',').indexOf('求職者数');
                let indexKYUJINRITU = reqArray[0].split(',').indexOf('求人倍率');

                let indexKYUJINSU_I = reqArray[0].split(',').indexOf('一般求人数');
                let indexKYUSYOKU_I = reqArray[0].split(',').indexOf('一般求職者数');
                let indexKYUJINRITU_I = reqArray[0].split(',').indexOf('一般求人倍率');

                let indexKYUJINSU_P = reqArray[0].split(',').indexOf('パート求人数');
                let indexKYUSYOKU_P = reqArray[0].split(',').indexOf('パート求職者数');
                let indexKYUJINRITU_P = reqArray[0].split(',').indexOf('パート求人倍率');

                //配列にpushして突っ込んでる?
                //キャラ.push(ROWW_DATA[0]);
                col_koumoku.push(ROWW_DATA[0]);
                if(ROWW_DATA[indexKYUJINSU] !== undefined) {
                    col_KYUJINSU.push(Number(ROWW_DATA[indexKYUJINSU]