Foliumの再学習Relaerningの2回目はChoroplethMapからStartいたします。
まずはChoroplethMapについてGemini先生に聞いてみました。
**ChoroplethMap(コロプレスマップ)**とは、地理的な領域(国、都道府県、市町村などの行政区画や、特定の地域)を、その領域に関連する統計データの値に応じて色やパターンで塗り分けた地図のことです。
簡単に言うと、**「データによって色が変わる地図」**です。
主な特徴と目的:
- 視覚的なデータの分布表示: 特定のデータ(人口密度、平均所得、感染者数、犯罪率など)が、地理的にどのように分布しているかを一目で視覚的に把握できます。
- 地域間の比較: 各領域の色の濃淡や種類を見ることで、異なる地域間でデータの値がどのように異なるかを比較できます。
- 傾向やパターンの特定: 地図上で色が変化する様子から、データの空間的な傾向やパターン(例:都市部に集中している、特定の沿岸地域で値が高いなど)を特定しやすくなります。
- 階級区分: 統計データは通常、いくつかの階級(範囲)に分けられ、それぞれの階級に異なる色や濃淡が割り当てられます。
- 相対値の表現に適している: 絶対量よりも、人口密度や一人当たりの収入など、面積や人口で正規化された**相対値(比率や平均)**を表現するのに特に適しています。これは、面積の大きい地域が絶対量で大きく見えてしまい、実態を誤解させる可能性があるためです。
例:
- 都道府県別の人口密度を、人口密度が高いほど濃い青色で、低いほど薄い青色で塗り分けた地図。
- 市町村別の世帯平均年収を、年収が高いほど緑色で、低いほど黄色で塗り分けた地図。
コロプレスマップは、政府機関の統計データや研究結果など、さまざまな分野で広く利用されている、非常に効果的なデータ可視化ツールです。
だそうです。ということで、日本統計局が提供しているe-StatのAPI機能を活用して、日本の都道府県別の人口の全人口に占める割合をDownLoadしてChoroplethMap表示にChallengeしようおと思います。
e-StatURL:https://www.e-stat.go.jp/
以前、e-StatのAPI機能を使って都道府県別の人口の全人口に占める割合についてMatPlotLibで表示する学習をしていたので、それを活用します。
ShikuuBlogURL:https://shikuuk.blogspot.com/2023/07/e-stat-with-python1-python.html
{'GET_STATS_DATA': {'RESULT': {'STATUS': 0, 'ERROR_MSG': '正常に終了しました。', 'DATE': '2025-05-21T19:55:23.837+09:00'}, 'PARAMETER': {'LANG': 'J', 'STATS_DATA_ID': '0003448233', 'NARROWING_COND': {'CODE_TIME_SELECT': 2021000000}, 'DATA_FORMAT': 'J', 'START_POSITION': 1, 'METAGET_FLG': 'Y'}, 'STATISTICAL_DATA': {'RESULT_INF': {'TOTAL_NUMBER': 48, 'FROM_NUMBER': 1, 'TO_NUMBER': 48}, 'TABLE_INF': {'@id': '0003448233', 'STAT_NAME': {'@code': '00200524', '$': '人口推計'}, 'GOV_ORG': {'@code': '00200', '$': '総務省'}, 'STATISTICS_NAME': '人口推計 各年10月1日現在人口 令和2年国勢調査基準 統計表', 'TITLE': {'@no': '006', '$': '都道府県別人口の割合-総人口'}, 'CYCLE': '年次', 'SURVEY_DATE': 0, 'OPEN_DATE': '2025-04-14', 'SMALL_AREA': 0, 'COLLECT_AREA': '該当なし', 'MAIN_CATEGORY': {'@code': '02', '$': '人口・世帯'}, 'SUB_CATEGORY': {'@code': '01', '$': '人口'}, 'OVERALL_TOTAL_NUMBER': 336, 'UPDATED_DATE': '2025-04-14', 'STATISTICS_NAME_SPEC': {'TABULATION_CATEGORY': '人口推計', 'TABULATION_SUB_CATEGORY1': '各年10月1日現在人口', 'TABULATION_SUB_CATEGORY2': '令和2年国勢調査基準', 'TABULATION_SUB_CATEGORY3': '統計表'}, 'DESCRIPTION': '', 'TITLE_SPEC': {'TABLE_NAME': '都道府県別人口の割合-総人口'}}, 'CLASS_INF': {'CLASS_OBJ': [{'@id': 'tab', '@name': '表章項目', 'CLASS': {'@code': '003', '@name': '人口割合', '@level': '', '@unit': '%'}}, {'@id': 'area', '@name': '全国・都道府県', 'CLASS': [{'@code': '00000', '@name': '全国', '@level': '1'}, {'@code': '01000', '@name': '北海道', '@level': '2'}, {'@code': '02000', '@name': '青森県', '@level': '2'}, {'@code': '03000', '@name': '岩手県', '@level': '2'}, {'@code': '04000', '@name': '宮城県', '@level': '2'}, {'@code': '05000', '@name': '秋田県', '@level': '2'}, {'@code': '06000', '@name': '山形県', '@level': '2'}, {'@code': '07000', '@name': '福島県', '@level': '2'}, {'@code': '08000', '@name': '茨城県', '@level': '2'}, {'@code': '09000', '@name': '栃木県', '@level': '2'}, {'@code': '10000', '@name': '群馬県', '@level': '2'}, {'@code': '11000', '@name': '埼玉県', '@level': '2'}, {'@code': '12000', '@name': '千葉県', '@level': '2'}, {'@code': '13000', '@name': '東京都', '@level': '2'}, {'@code': '14000', '@name': '神奈川県', '@level': '2'}, {'@code': '15000', '@name': '新潟県', '@level': '2'}, {'@code': '16000', '@name': '富山県', '@level': '2'}, {'@code': '17000', '@name': '石川県', '@level': '2'}, {'@code': '18000', '@name': '福井県', '@level': '2'}, {'@code': '19000', '@name': '山梨県', '@level': '2'}, {'@code': '20000', '@name': '長野県', '@level': '2'}, {'@code': '21000', '@name': '岐阜県', '@level': '2'}, {'@code': '22000', '@name': '静岡県', '@level': '2'}, {'@code': '23000', '@name': '愛知県', '@level': '2'}, {'@code': '24000', '@name': '三重県', '@level': '2'}, {'@code': '25000', '@name': '滋賀県', '@level': '2'}, {'@code': '26000', '@name': '京都府', '@level': '2'}, {'@code': '27000', '@name': '大阪府', '@level': '2'}, {'@code': '28000', '@name': '兵庫県', '@level': '2'}, {'@code': '29000', '@name': '奈良県', '@level': '2'}, {'@code': '30000', '@name': '和歌山県', '@level': '2'}, {'@code': '31000', '@name': '鳥取県', '@level': '2'}, {'@code': '32000', '@name': '島根県', '@level': '2'}, {'@code': '33000', '@name': '岡山県', '@level': '2'}, {'@code': '34000', '@name': '広島県', '@level': '2'}, {'@code': '35000', '@name': '山口県', '@level': '2'}, {'@code': '36000', '@name': '徳島県', '@level': '2'}, {'@code': '37000', '@name': '香川県', '@level': '2'}, {'@code': '38000', '@name': '愛媛県', '@level': '2'}, {'@code': '39000', '@name': '高知県', '@level': '2'}, {'@code': '40000', '@name': '福岡県', '@level': '2'}, {'@code': '41000', '@name': '佐賀県', '@level': '2'}, {'@code': '42000', '@name': '長崎県', '@level': '2'}, {'@code': '43000', '@name': '熊本県', '@level': '2'}, {'@code': '44000', '@name': '大分県', '@level': '2'}, {'@code': '45000', '@name': '宮崎県', '@level': '2'}, {'@code': '46000', '@name': '鹿児島県', '@level': '2'}, {'@code': '47000', '@name': '沖縄県', '@level': '2'}]}, {'@id': 'time', '@name': '時間軸(年)', 'CLASS': {'@code': '2021000000', '@name': '2021年', '@level': '1'}}]}, 'DATA_INF': {'NOTE': [{'@char': '***', '$': '該当数値がないもの'}, {'@char': '-', '$': '該当数値がないもの\u3000'}], 'VALUE': [{'@tab': '003', '@area': '00000', '@time': '2021000000', '@unit': '%', '$': '100.00'}, {'@tab': '003', '@area': '01000', '@time': '2021000000', '@unit': '%', '$': '4.13'}, {'@tab': '003', '@area': '02000', '@time': '2021000000', '@unit': '%', '$': '0.97'}, {'@tab': '003', '@area': '03000', '@time': '2021000000', '@unit': '%', '$': '0.95'}, {'@tab': '003', '@area': '04000', '@time': '2021000000', '@unit': '%', '$': '1.82'}, {'@tab': '003', '@area': '05000', '@time': '2021000000', '@unit': '%', '$': '0.75'}, {'@tab': '003', '@area': '06000', '@time': '2021000000', '@unit': '%', '$': '0.84'}, {'@tab': '003', '@area': '07000', '@time': '2021000000', '@unit': '%', '$': '1.44'}, {'@tab': '003', '@area': '08000', '@time': '2021000000', '@unit': '%', '$': '2.27'}, {'@tab': '003', '@area': '09000', '@time': '2021000000', '@unit': '%', '$': '1.53'}, {'@tab': '003', '@area': '10000', '@time': '2021000000', '@unit': '%', '$': '1.54'}, {'@tab': '003', '@area': '11000', '@time': '2021000000', '@unit': '%', '$': '5.85'}, {'@tab': '003', '@area': '12000', '@time': '2021000000', '@unit': '%', '$': '5.00'}, {'@tab': '003', '@area': '13000', '@time': '2021000000', '@unit': '%', '$': '11.16'}, {'@tab': '003', '@area': '14000', '@time': '2021000000', '@unit': '%', '$': '7.36'}, {'@tab': '003', '@area': '15000', '@time': '2021000000', '@unit': '%', '$': '1.73'}, {'@tab': '003', '@area': '16000', '@time': '2021000000', '@unit': '%', '$': '0.82'}, {'@tab': '003', '@area': '17000', '@time': '2021000000', '@unit': '%', '$': '0.90'}, {'@tab': '003', '@area': '18000', '@time': '2021000000', '@unit': '%', '$': '0.61'}, {'@tab': '003', '@area': '19000', '@time': '2021000000', '@unit': '%', '$': '0.64'}, {'@tab': '003', '@area': '20000', '@time': '2021000000', '@unit': '%', '$': '1.62'}, {'@tab': '003', '@area': '21000', '@time': '2021000000', '@unit': '%', '$': '1.56'}, {'@tab': '003', '@area': '22000', '@time': '2021000000', '@unit': '%', '$': '2.87'}, {'@tab': '003', '@area': '23000', '@time': '2021000000', '@unit': '%', '$': '5.99'}, {'@tab': '003', '@area': '24000', '@time': '2021000000', '@unit': '%', '$': '1.40'}, {'@tab': '003', '@area': '25000', '@time': '2021000000', '@unit': '%', '$': '1.12'}, {'@tab': '003', '@area': '26000', '@time': '2021000000', '@unit': '%', '$': '2.04'}, {'@tab': '003', '@area': '27000', '@time': '2021000000', '@unit': '%', '$': '7.02'}, {'@tab': '003', '@area': '28000', '@time': '2021000000', '@unit': '%', '$': '4.33'}, {'@tab': '003', '@area': '29000', '@time': '2021000000', '@unit': '%', '$': '1.05'}, {'@tab': '003', '@area': '30000', '@time': '2021000000', '@unit': '%', '$': '0.73'}, {'@tab': '003', '@area': '31000', '@time': '2021000000', '@unit': '%', '$': '0.44'}, {'@tab': '003', '@area': '32000', '@time': '2021000000', '@unit': '%', '$': '0.53'}, {'@tab': '003', '@area': '33000', '@time': '2021000000', '@unit': '%', '$': '1.50'}, {'@tab': '003', '@area': '34000', '@time': '2021000000', '@unit': '%', '$': '2.21'}, {'@tab': '003', '@area': '35000', '@time': '2021000000', '@unit': '%', '$': '1.06'}, {'@tab': '003', '@area': '36000', '@time': '2021000000', '@unit': '%', '$': '0.57'}, {'@tab': '003', '@area': '37000', '@time': '2021000000', '@unit': '%', '$': '0.75'}, {'@tab': '003', '@area': '38000', '@time': '2021000000', '@unit': '%', '$': '1.05'}, {'@tab': '003', '@area': '39000', '@time': '2021000000', '@unit': '%', '$': '0.55'}, {'@tab': '003', '@area': '40000', '@time': '2021000000', '@unit': '%', '$': '4.08'}, {'@tab': '003', '@area': '41000', '@time': '2021000000', '@unit': '%', '$': '0.64'}, {'@tab': '003', '@area': '42000', '@time': '2021000000', '@unit': '%', '$': '1.03'}, {'@tab': '003', '@area': '43000', '@time': '2021000000', '@unit': '%', '$': '1.38'}, {'@tab': '003', '@area': '44000', '@time': '2021000000', '@unit': '%', '$': '0.89'}, {'@tab': '003', '@area': '45000', '@time': '2021000000', '@unit': '%', '$': '0.85'}, {'@tab': '003', '@area': '46000', '@time': '2021000000', '@unit': '%', '$': '1.26'}, {'@tab': '003', '@area': '47000', '@time': '2021000000', '@unit': '%', '$': '1.17'}]}}}}
タブ | 都道府県コード | 調査年 | 単位 | 人口比(対全国人口) | |
---|---|---|---|---|---|
0 | 003 | 00000 | 2021000000 | % | 100.00 |
1 | 003 | 01000 | 2021000000 | % | 4.13 |
2 | 003 | 02000 | 2021000000 | % | 0.97 |
3 | 003 | 03000 | 2021000000 | % | 0.95 |
4 | 003 | 04000 | 2021000000 | % | 1.82 |
タブ | 都道府県コード | 調査年 | 単位 | 人口比(対全国人口) | N03_001 | |
---|---|---|---|---|---|---|
0 | 003 | 00000 | 2021000000 | % | 100.00 | 全国 |
1 | 003 | 01000 | 2021000000 | % | 4.13 | 北海道 |
2 | 003 | 02000 | 2021000000 | % | 0.97 | 青森県 |
3 | 003 | 03000 | 2021000000 | % | 0.95 | 岩手県 |
4 | 003 | 04000 | 2021000000 | % | 1.82 | 宮城県 |
N03_001 | geometry | simplified_geometry | タブ | 都道府県コード | 調査年 | 単位 | 人口比(対全国人口) | |
---|---|---|---|---|---|---|---|---|
0 | 三重県 | MULTIPOLYGON (((136.02156 33.7343, 136.02154 3... | MULTIPOLYGON (((136.02158 33.73431, 136.02153 ... | 003 | 24000 | 2021000000 | % | 1.40 |
1 | 京都府 | MULTIPOLYGON (((134.89358 35.64858, 134.89358 ... | MULTIPOLYGON (((134.89369 35.64859, 134.89358 ... | 003 | 26000 | 2021000000 | % | 2.04 |
2 | 佐賀県 | MULTIPOLYGON (((129.78926 33.44452, 129.7893 3... | MULTIPOLYGON (((129.78922 33.4445, 129.7893 33... | 003 | 41000 | 2021000000 | % | 0.64 |
3 | 兵庫県 | MULTIPOLYGON (((134.38287 34.71978, 134.38288 ... | MULTIPOLYGON (((134.38286 34.71979, 134.38287 ... | 003 | 28000 | 2021000000 | % | 4.33 |
4 | 北海道 | MULTIPOLYGON (((139.34092 41.49493, 139.34094 ... | MULTIPOLYGON (((139.34074 41.49497, 139.34089 ... | 003 | 01000 | 2021000000 | % | 4.13 |
N03_001 | N03_002 | N03_003 | N03_004 | N03_005 | N03_007 | geometry | |
---|---|---|---|---|---|---|---|
0 | 北海道 | 石狩振興局 | None | 札幌市 | 中央区 | 01101 | POLYGON ((141.25694 42.99782, 141.2563 42.9978... |
1 | 北海道 | 石狩振興局 | None | 札幌市 | 北区 | 01102 | POLYGON ((141.33325 43.07505, 141.3326 43.0757... |
2 | 北海道 | 石狩振興局 | None | 札幌市 | 東区 | 01103 | POLYGON ((141.37341 43.0684, 141.37333 43.0684... |
3 | 北海道 | 石狩振興局 | None | 札幌市 | 白石区 | 01104 | POLYGON ((141.38202 43.04832, 141.38193 43.048... |
4 | 北海道 | 石狩振興局 | None | 札幌市 | 豊平区 | 01105 | POLYGON ((141.36371 42.94154, 141.36378 42.941... |
... | ... | ... | ... | ... | ... | ... | ... |
124128 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.93299 24.4517, 122.93299 24.4517... |
124129 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.93396 24.4482, 122.93396 24.4482... |
124130 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.94213 24.44395, 122.94214 24.443... |
124131 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.99876 24.43985, 122.99875 24.439... |
124132 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.93308 24.45176, 122.93308 24.451... |
124133 rows × 7 columns
N03_001 | N03_002 | N03_003 | N03_004 | N03_005 | N03_007 | geometry | |
---|---|---|---|---|---|---|---|
0 | 北海道 | 石狩振興局 | None | 札幌市 | 中央区 | 01101 | POLYGON ((141.25694 42.99782, 141.2563 42.9978... |
1 | 北海道 | 石狩振興局 | None | 札幌市 | 北区 | 01102 | POLYGON ((141.33325 43.07505, 141.3326 43.0757... |
2 | 北海道 | 石狩振興局 | None | 札幌市 | 東区 | 01103 | POLYGON ((141.37341 43.0684, 141.37333 43.0684... |
3 | 北海道 | 石狩振興局 | None | 札幌市 | 白石区 | 01104 | POLYGON ((141.38202 43.04832, 141.38193 43.048... |
4 | 北海道 | 石狩振興局 | None | 札幌市 | 豊平区 | 01105 | POLYGON ((141.36371 42.94154, 141.36378 42.941... |
... | ... | ... | ... | ... | ... | ... | ... |
124128 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.93299 24.4517, 122.93299 24.4517... |
124129 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.93396 24.4482, 122.93396 24.4482... |
124130 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.94213 24.44395, 122.94214 24.443... |
124131 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.99876 24.43985, 122.99875 24.439... |
124132 | 沖縄県 | None | 八重山郡 | 与那国町 | None | 47382 | POLYGON ((122.93308 24.45176, 122.93308 24.451... |
124133 rows × 7 columns
47種類もの「視覚的に識別しやすい」色を生成するのは、一筋縄ではいきません。単にランダムに生成するだけでは、似たような色が多くなってしまい、区別がつきにくくなる可能性が高いです。
しかし、Pythonにはこれを助けるためのライブラリや手法がいくつか存在します。
1. distinctipy
ライブラリを使う (推奨)
distinctipy
は、その名の通り「視覚的に区別しやすい色」を生成するために設計されたPythonライブラリです。指定した数だけ、最も異なる色を生成しようと試みます。
まず、インストールします。
pip install distinctipy
次に、Pythonコードで色を生成します。
import distinctipy
# 生成したい色の数
num_colors = 47
# 視覚的に区別しやすい色をN個生成
# return_hex=True を指定すると、直接16進数カラーコードのリストが返されます
colors_hex = distinctipy.get_colors(num_colors, return_hex=True)
print(f"{num_colors}個の識別しやすいカラーコード:")
for i, hex_color in enumerate(colors_hex):
print(f"Color {i+1}: {hex_color}")
# (オプション) 生成された色を視覚的に確認する
# matplotlib と pandas が必要です (pip install distinctipy[extras] でインストールできます)
# import matplotlib.pyplot as plt
# import pandas as pd
# distinctipy.color_swatch(colors_hex)
# plt.show()
このライブラリは、色空間(HSL、Labなど)を考慮して、色相、彩度、明度を調整しながら、既存の色から最も遠い色を見つけ出すアルゴリズムを使用しています。
2. HSL/HSV色空間で色相を均等に分割する方法
RGB色空間でランダムに色を生成すると似た色が出やすいですが、HSL(Hue, Saturation, Lightness)やHSV(Hue, Saturation, Value)色空間は、人間の色の知覚に近い形で色を表現するため、視覚的に区別しやすい色を生成するのに役立ちます。
特に「色相 (Hue)」を均等に分割することで、多様な色を効率的に生成できます。
import colorsys
def get_distinct_colors_hsl(n_colors, saturation=0.7, lightness=0.5):
"""
HSL色空間を使ってN個の識別しやすい色を生成し、16進数カラーコードで返す。
"""
hex_colors = []
for i in range(n_colors):
# 色相 (hue) を均等に分割
hue = i / n_colors
# HSLをRGBに変換 (0.0-1.0の範囲)
r, g, b = colorsys.hls_to_rgb(hue, lightness, saturation)
# RGBを0-255の整数に変換
r_int = int(r * 255)
g_int = int(g * 255)
b_int = int(b * 255)
# 16進数カラーコードに変換
hex_color = f"#{r_int:02x}{g_int:02x}{b_int:02x}"
hex_colors.append(hex_color)
return hex_colors
# 47種類の色を生成
num_colors = 47
colors_hsl = get_distinct_colors_hsl(num_colors)
print(f"{num_colors}個のHSLベースのカラーコード:")
for i, hex_color in enumerate(colors_hsl):
print(f"Color {i+1}: {hex_color}")
# saturation(彩度)とlightness(明度)を調整して、色のバリエーションを増やすこともできます。
# 例えば、よりパステル調の色にするには lightness を上げたり、saturation を下げたりします。
# colors_hsl_pastel = get_distinct_colors_hsl(num_colors, saturation=0.5, lightness=0.8)
この方法の利点はシンプルさですが、色の数が多くなると、隣接する色相の色が似て見えたり、明度や彩度が固定されるためバリエーションが限られる可能性があります。
3. Matplotlibのカラーマップを利用する
matplotlib
はデータ可視化ライブラリですが、多くの優れたカラーマップ(色の連続的なグラデーション)を提供しています。これらのカラーマップから指定した数の色を抽出し、16進数に変換することができます。
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
def get_matplotlib_colors(n_colors, colormap_name='viridis'):
"""
MatplotlibのカラーマップからN個の色を抽出し、16進数カラーコードで返す。
"""
hex_colors = []
# カラーマップを取得
colormap = cm.get_cmap(colormap_name)
for i in range(n_colors):
# 0.0から1.0の範囲で均等に値をサンプリング
rgba_color = colormap(i / (n_colors - 1)) # n_colors-1 で最後の色まで含める
# RGBA (0.0-1.0) を RGB (0-255) に変換し、16進数に
r_int = int(rgba_color[0] * 255)
g_int = int(rgba_color[1] * 255)
b_int = int(rgba_color[2] * 255)
hex_color = f"#{r_int:02x}{g_int:02x}{b_int:02x}"
hex_colors.append(hex_color)
return hex_colors
# 47種類の色を生成('viridis'カラーマップを使用)
num_colors = 47
colors_mpl = get_matplotlib_colors(num_colors, colormap_name='viridis')
print(f"{num_colors}個のMatplotlibベースのカラーコード ('viridis'より):")
for i, hex_color in enumerate(colors_mpl):
print(f"Color {i+1}: {hex_color}")
# 他のカラーマップも試してみる (例: 'plasma', 'cividis', 'tab20', 'Dark2'など)
# 'tab20' は20色しかないので、47色には不向きです。連続的なカラーマップが適しています。
# colors_mpl_plasma = get_matplotlib_colors(num_colors, colormap_name='plasma')
Matplotlibのカラーマップは、科学的なデータ可視化のために色の識別性や色覚異常への配慮がされているものも多く、有効な選択肢です。
どの方法を選ぶべきか?
distinctipy
: 最も推奨されます。視覚的な識別性を最適化するよう設計されているため、色の数が多くても比較的区別しやすい色が得られます。- HSL/HSVベース: 実装が非常にシンプルで、基本的な要件を満たすなら十分です。ただし、色の数が多くなると、隣接する色が似て見えることがあります。
- Matplotlibカラーマップ: 既存の高品質なカラーマップを利用できるため、特定のグラデーションやテーマに沿った色が必要な場合に便利です。
47種類もの色を完璧に「識別しやすい」ものにするのは、人間にとって困難なタスクですが、これらの方法を使えば、ある程度の識別性を確保したカラーコードのリストを生成できます。