Python で記述統計を自動化する 7 つのステップ
本文の状態
日本語全文を表示中
詳細モードで約17分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
KDnuggets
この記事は、Python を用いて記述統計の自動化パイプラインを構築する 7 つのステップを解説しており、開発者が手作業による分析から脱却し、再現性のあるレポート作成を実現するための具体的な手法を示している。
AI深層分析を開く2026年8月6日 22:16
AI深層分析
キーポイント
環境構築とデータセットの選定
pandas, seaborn, skimpy などの主要ライブラリをインストールし、欠損値やカテゴリカル変数が含まれる「Palmer Penguins」データセットを実例として取り上げる。
データプロファイリングライブラリの名称変更
かつて pandas-profiling や ydata-profiling と呼ばれていたライブラリが、2026 年 4 月に fg-data-profiling に改名されたことを明記し、新規プロジェクトでは新パッケージの使用を推奨する。
自動化パイプラインの構築アプローチ
df.describe() や手動でのリフォーマットといった反復作業を廃止し、1〜2 行で整形されたサマリーテーブルや研究論文風の「Table 1」を生成するツール群の利用方法を提案している。
再現性の高いワークフローの確立
一時的なスニペットの羅列ではなく、一度構築すれば再利用可能な自動化パイプラインを作ることで、分析効率とレポートの品質を向上させる手法を体系化している。
describe() の基本的な機能と限界
Pandas の describe() は即座に実行可能だが、デフォルトではカテゴリカル列を無視し、欠損値の割合や分布の形状(歪度など)を示さない。
重要な引用
The Python ecosystem now has tools that take you from a raw DataFrame to a formatted, shareable summary table in one or two lines
It was initially pandas-profiling, became ydata-profiling in 2023, and was renamed again to fg-data-profiling in April 2026.
This tutorial walks you through the 7 steps to build a repeatable pipeline rather than a pile of one-off snippets.
This is genuinely useful, but notice its blind spots.
編集コメントを表示
編集コメント
この記事は特定の AI モデルや企業の動向を報じるものではなく、データエンジニアリングのベストプラクティスに関する技術解説である。しかし、AI 活用における前処理工程の効率化という文脈では、実務者にとって有益な情報源となる。
Source Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
image**
# イントロダクション
すべての分析は同じように始まります:データセットを読み込み、その中身が実際に何であるかを把握しようとします。行数はいくつ?数値型のカラムはどれか?欠損値はどの程度あるか?何か極端に歪んでいないか?これらの質問に対する答えを、私たちが千回以上も入力してきた同じ df.describe() や df.isna().sum(), df.groupby(...).agg(...) のスニペットをコピー&ペーストして得て、レポートに組み込む際に手動で出力を再フォーマットするという方法で返すことがほとんどです。
それは無駄な労力です。Python エコシステムには、生データフレームから数行のコードだけで整形された共有可能な要約テーブルを作成するツールや、研究論文で主に目にするような「Table 1」の作成に特化したツールが既に存在します。このチュートリアルでは、バラバラのスニペットの山ではなく、繰り返し再利用可能なパイプラインを構築するための 7 つのステップを解説していきます。ここでは Palmer Penguins dataset を通して説明を行います。これは小さく、オープンソースであり、数値型とカテゴリカル型の列が現実的に混合しており、実際の欠損値も含まれ、自然なグループ化変数(種別)も備えています。では、始めましょう。
# 1. 環境のセットアップとデータの読み込み
本チュートリアルで使用するパッケージをインストールしてください:
pip install pandas seaborn skimpy tableone great-tables fg-data-profiling
最後のツールに関する重要な注意点:人気のプロファイリングライブラリは一度ではなく複数回名前を変更されています。当初は pandas-profiling でしたが、2023 年に ydata-profiling に改名され、さらに 2026 年 4 月には fg-data-profiling と再度改名されました。古い ydata-profiling パッケージはまだインストールして実行可能ですが、更新は行われていないため、新しいプロジェクトでは fg-data-profiling を優先して使用すべきです。ステップ 5 では両方のインポートスタイルを解説します。
次にデータをロードしましょう。Seaborn (https://seaborn.pydata.org/) にはビルトインのペンギンデータセットが含まれており、ダウンロードの手間が省けます:
import pandas as pd
import seaborn as sns
df = sns.load_dataset("penguins")
print(df.shape)
print(df.dtypes)
print(df.isna().sum())
出力結果:
(344, 7)
species object
island object
bill_length_mm float64
bill_depth_mm float64
flipper_length_mm float64
body_mass_g float64
sex object
dtype: object
species 0
island 0
bill_length_mm 2
bill_depth_mm 2
flipper_length_mm 2
body_mass_g 2
sex 11
dtype: int64
7 つの列が表示されます。そのうち 3 つはカテゴリカル(species, island, sex)で、残りの 4 つは数値測定値(bill_length_mm, bill_depth_mm, flipper_length_mm, body_mass_g)です。各測定値には欠損値が 2 件ずつあり、sex 列には 11 件の欠損値があります。この詳細は覚えておいてください。後ほど各ツールがこの欠損データをどのように報告するかを確認します。
# 2. df.describe() でベースラインを取得する
**
Pandas の組み込み関数 describe() は明白な出発点であり、その理由も十分にあります。これは瞬時に実行でき、追加のインストールは不要です:
df.describe().round(2)
出力結果:
bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
count 342.00 342.00 342.00 342.00
mean 43.92 17.15 200.92 4201.75
std 5.46 1.97 14.06 801.95
min 32.10 13.10 172.00 2700.00
25% 39.22 15.60 190.00 3550.00
50% 44.45 17.30 197.00 4050.00
75% 48.50 18.70 213.00 4750.00
max 59.60 21.50 231.00 6300.00
これは確かに有用ですが、その盲点を注意深く見る必要があります。デフォルトでは、カテゴリカル列(categorical columns)を完全に無視します。非null(non-null)値の数はカウントされますが、欠損値の割合を直接示すことはありません。また、5 数要約(five-number summary)で止まり、歪度(skewness)や尖度(kurtosis)、分布形状に関する洞察は得られません。素早い確認用としては問題ありませんが、報告書の基盤として使うには不十分です。次のステップでは、Pandas を離れることなくこれらのギャップを埋めることができます。
# 3. include, .agg(), groupby を活用して Pandas の可能性を広げる
外部パッケージに頼る前に、Pandas 単体でどこまでできるかを知っておく価値があります。多くの日常的な作業においては、これだけで十分だからです。
まず、カテゴリカル列を include="all" を指定して同じ要約に統合します:
df.describe(include="all").round(2)
出力結果:
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex
count 344 344 342.00 342.00 342.00 342.00 333
unique 3 3 NaN NaN NaN NaN 2
top Adelie Biscoe NaN NaN NaN NaN Male
freq 152 168 NaN NaN NaN NaN 168
mean NaN NaN 43.92 17.15 200.92 4201.75 NaN
std NaN NaN 5.46 1.97 14.06 801.95 NaN
min NaN NaN 32.10 13.10 172.00 2700.00 NaN
25% NaN NaN 39.22 15.60 190.00 3550.00 NaN
50% NaN NaN 44.45 17.30 197.00 4050.00 NaN
75% NaN NaN 48.50 18.70 213.00 4750.00 NaN
max NaN NaN 59.60 21.50 231.00 6300.00 NaN
これで、テキスト列についても一意値 (unique)、最頻値 (top)、出現頻度 (freq) が得られ、数値統計量と共に表示されます。また、特定の統計量が適用できないセルには NaN で埋められます。1 つの表にすべての列が含まれます。
次に、.agg() を使用してカスタムの要約を作成し、describe() が省略する歪度や尖度などの統計量を含め、どの統計量が表示されるかを完全に制御できるようにします。さらに、欠損データの割合も追加しましょう:
numeric = df.select_dtypes("number")
summary = numeric.agg(["mean", "median", "std", "skew", "kurt"]).T
summary["missing_pct"] = df[numeric.columns].isna().mean().mul(100).round(1)
summary.round(2)
出力:
mean median std skew kurt missing_pct
bill_length_mm 43.92 44.45 5.46 0.05 -0.88 0.6
bill_depth_mm 17.15 17.30 1.97 -0.14 -0.91 0.6
flipper_length_mm 200.92 197.00 14.06 0.35 -0.98 0.6
body_mass_g 4201.75 4050.00 801.95 0.47 -0.72 0.6
そして三つ目 — これが人々が忘れがちなポイントですが— describe() の前に groupby() をチェーンして、単一行で層別化された要約を取得します:
df.groupby("species")["body_mass_g"].describe().round(1)
出力:
count mean std min 25% 50% 75% max
species
Adelie 151.0 3700.7 458.6 2850.0 3350.0 3700.0 4000.0 4775.0
Chinstrap 68.0 3733.1 384.3 2700.0 3487.5 3700.0 3950.0 4800.0
Gentoo 123.0 5076.0 504.1 3950.0 4700.0 5000.0 5500.0 6300.0
習得すべきパターン:select_dtypes で列を選択し、.agg([...]) で統計量を選び、groupby で層別化を行う。この 3 つの組み合わせは、依存関係を一切必要とせずに、実際のレポート作成ニーズの驚くほど大きな部分をカバーします。残りのステップは、時間の節約、仕上げの追加、「十分だ」という判断が通用しないケースへの対応に関するものです。
# 4. skimpy を使ってより豊富なコンソール要約を得る
describe() よりも詳細な情報が必要だが、手作業で組み立てるのは面倒だという場合、skimpy** が最適な選択肢です。これは、コンソールまたはノートブック上で実行され、すべての列タイプを一度に処理する、強化された describe() のようなものです。Pandas および Polars の両方の DataFrame で動作します。
from skimpy import skim
skim(df)
単一の呼び出しで構造化されたレポートが出力されます:データサマリー(行数と列数)、データタイプ別の内訳、平均値・標準偏差・完全な百分位範囲を含む数値表、各列ごとのインライン ASCII ヒストグラム、そして文字列列用の別テーブル(文字数や最も頻出/最少頻出の値など)が含まれます。欠損データは、期待される場所に、カウントとパーセンテージの両方で報告されます。
出力:
╭──────────────────────────────────────────────── skimpy summary ─────────────────────────────────────────────────╮
│ データサマリー データタイプ │
│ ┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┓ ┏━━━━━━━━━━━━━┳━━━━━━━┓ │
│ ┃ データフレーム ┃ 値 ┃ ┃ カラムタイプ ┃ 数 ┃ │
│ ┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━┩ ┡━━━━━━━━━━━━━╇━━━━━━━┩ │
│ │ 行数 │ 344 │ │ float64 │ 4 │ │
│ │ カラム数 │ 7 │ │ string │ 3 │ │
│ └───────────────────┴────────┘ └─────────────┴───────┘ │
│ 数値 │
│ ┏━━━━━━━━━━━━━━━━━━━━┳━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━┳━━━━━━┳━━━━━━━━┓ │
│ ┃ カラム ┃ NA ┃ NA % ┃ 平均 ┃ sd ┃ p0 ┃ p25 ┃ p50 ┃ p75 ┃ p100 ┃ hist ┃ │
│ ┡━━━━━━━━━━━━━━━━━━━━╇━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━╇━━━━━━╇━━━━━━━━┩ │
│ │ bill_length_mm │ 2 │ 0.5813953488372093 │ 43.92 │ 5.46 │ 32.1 │ 39.23 │ 44.45 │ 48.5 │ 59.6 │ ▃█▆█▃ │ │
│ │ bill_depth_mm │ 2 │ 0.5813953488372093 │ 17.15 │ 1.975 │ 13.1 │ 15.6 │ 17.3 │ 18.7 │ 21.5 │ ▄▅▆█▆▂ │ │
│ │ flipper_length_mm │ 2 │ 0.5813953488372093 │ 200.9 │ 14.06 │ 172 │ 190 │ 197 │ 213 │ 231 │ ▂██▄▆▃ │ │
│ │ body_mass_g │ 2 │ 0.5813953488372093 │ 4202 │ 802 │ 2700 │ 3550 │ 4050 │ 4750 │ 6300 │ ▂█▆▄▃▁ │ │
│ └────────────────────┴────┴────────────────────┴───────┴───────┴──────┴───────┴───────┴──────┴──────┴────────┘ │
│ 文字列 │
│ ┏━━━━━━━━━┳━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━┓ │
│ ┃ カラム ┃ NA ┃ NA % ┃ 最短 ┃ 最長 ┃ min ┃ max ┃ chars/row ┃ words/row ┃ total words┃ │
│ ┡━━━━━━━━━╇━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━┩ │
│ │ species │ 0 │ 0 │ Adelie │ Chinstrap │ Adelie │ Gentoo │ 6.59 │ 1.00 │ 344 │ │
│ │ island │ 0 │ 0 │ Dream │ Torgersen │ Biscoe │ Torgersen │ 6.09 │ 1.00 │ 344 │ │
│ │ sex │11 │ 3.19767442 │ Male │ Female │ Female │ Male │ 4.99 │ 0.97 │ 333 │ │
│ └─────────┴────┴────────────┴──────────┴───────────┴────────┴───────────┴────────────┴───────────┴────────────┘ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
インラインヒストグラムは目玉機能です。プロットライブラリを開かずに、各分布の形状を把握できます。対話型の探索には skimpy が適した中間点と言えます:describe() よりもはるかに情報量が多く、完全な HTML レポートよりも軽量です。
# 5. プロファイリングによる完全な対話型レポートの生成
**
分布、相関、相互作用、重複検出、データ品質警告など「完全な」全体像が必要な場合、包括的なプロファイルレポートを生成するのが最適です。これは多くの分析担当者が半日かけて行っていた探索的プロットを置き換えた、たった 1 行のコードです。
メンテナンスされているパッケージを使用する場合:
from data_profiling import ProfileReport # fg-data-profiling
profile = ProfileReport(df, title="Penguins Profiling Report", explorative=True)
profile.to_file("penguins_report.html")
レガシーなパッケージを使用する場合は、インポート行のみが異なります:
import ydata_profiling # legacy ydata-profiling
出力されるのは、概要(サイズ、メモリ使用量、重複行数)、変数ごとの詳細記述(記述統計およびヒストグラム)、複数の係数による相関分析、欠損値分析、そして歪度、高カルディナリティ、定数カラムなどを自動的に警告するアラートを含む、自己完結型の対話型 HTML ファイルです。

生成されたプロファイリングレポートの一部
唯一のトレードオフは速度です:完全なレポートでは多くの計算が行われるため、大規模データセットでは処理が遅くなります。これを解決するための2つの引数があります。最も高価な計算を無効にするには minimal=True を使用し、データの全体像をつかむだけであれば、フレーム全体ではなくサンプルのプロファイルを作成します。
profile = ProfileReport(df.sample(frac=0.5), minimal=True)
また、2 つのデータセットを並べて比較するための .compare() メソッドもあります。これは、トレーニングセットと本番データの間のドリフトや、2 つの期間間の違いを発見する際に非常に役立ちます。
# 6. tableone を使用した実用的な「Table 1」の構築
これまでの内容はすべて *あなた自身* のための探索支援ツールです。tableone** はあなたの読者のためにあります。これは、ほぼすべての臨床研究および定量的研究論文で冒頭に掲載される層別化されたベースライン特性表(したがって「Table 1」と呼ばれる)を生成するもので、査読者が期待する書式と統計情報を提供します。
from tableone import TableOne
data = df.dropna(subset=["sex"])
columns = ["bill_length_mm", "bill_depth_mm",
"flipper_length_mm", "body_mass_g", "island", "sex"]
categorical = ["island", "sex"]
nonnormal = ["body_mass_g"] # 平均 (標準偏差) の代わりに中央値 [IQR] で要約
table1 = TableOne(
data,
columns=columns,
categorical=categorical,
nonnormal=nonnormal,
groupby="species",
pval=True,
smd=True,
)
print(table1.tabulate(tablefmt="github"))
その結果、適切に書式設定された表が得られます。連続変数は平均(標準偏差)、カテゴリカル変数は件数(%)、非正規とフラグ付けされた変数は中央値 [第1四分位数,第3四分位数] として表示され、グループ化変数ごとに層別化されます。さらに、欠損データのカラム、p 値、およびグループ間の標準化平均差 (SMD) も含まれます。
| Missing | Overall | Adelie | Chinstrap | Gentoo | SMD (Adelie,Chinstrap) | SMD (Adelie,Gentoo) | SMD (Chinstrap,Gentoo) | P-Value | ||
|---|---|---|---|---|---|---|---|---|---|---|
| n | 333 | 146 | 68 | 119 | ||||||
| bill_length_mm, mean (SD) | 0 | 44.0 (5.5) | 38.8 (2.7) | 48.8 (3.3) | 47.6 (3.1) | 3.315 | 3.023 | -0.393 | <0.001 | |
| bill_depth_mm, mean (SD) | 0 | 17.2 (2.0) | 18.3 (1.2) | 18.4 (1.1) | 15.0 (1.0) | 0.062 | -3.022 | -3.220 | <0.001 | |
| flipper_length_mm, mean (SD) | 0 | 201.0 (14.0) | 190.1 (6.5) | 195.8 (7.1) | 217.2 (6.6) | 0.837 | 4.140 | 3.119 | <0.001 | |
| body_mass_g, median [Q1,Q3] | 0 | 4050.0 [3550.0,4775.0] | 3700.0 [3362.5,4000.0] | 3700.0 [3487.5,3950.0] | 5050.0 [4700.0,5500.0] | 0.064 | 2.885 | 3.043 | <0.001 | |
| island, n (%) | Biscoe | 163 (48.9) | 44 (30.1) | 0 (0.0) | 119 (100.0) | 1.819 | 2.153 | nan | <0.001 | |
| Dream | 123 (36.9) | 55 (37.7) | 68 (100.0) | 0 (0.0) | ||||||
| Torgersen | 47 (14.1) | 47 (32.2) | 0 (0.0) | 0 (0.0) | ||||||
| sex, n (%) | Female | 165 (49.5) | 73 (50.0) | 34 (50.0) | 58 (48.7) | <0.001 | 0.025 | 0.025 | 0.976 | |
| Male | 168 (50.5) | 73 (50.0) | 34 (50.0) | 61 (51.3) |
真の成果はエクスポートにあります。TableOne オブジェクトは、原稿に必要な形式(LaTeX:Overleaf への貼り付け用、HTML、Markdown、CSV)に直接変換されます。
table1.to_latex("table1.tex")
table1.to_html("table1.html")
table1.to_csv("table1.csv")
パッケージの著者が強調し、私も同様に強調する重要な点があります。自動化された統計解析は、判断力を代替するものではないということです。どの検定を行うか、変数が本当に正規分布に従っているかどうか、欠損値をどう扱うかなどは、出版される前に必ず人間のレビューが必要です。tableone は退屈な作業を取り除くものであり、責任まで取り除くものではありません。
# 7. Great Tables を用いて出版品質のテーブルに仕上げる
**
tableone は研究用のテーブルを特にフォーマットするために設計されています。一方、*それ以外の*要約(ビジネスレポート、スライド、README など)については、Great Tables が、R 言語の gt パッケージと同様に、単なる DataFrame をスタイル付けされたプレゼンテーション用のテーブルに変換します。これは Pandas または Polars のフレームを受け取り、HTML または画像としてレンダリングします。
ステップ 3 で作成したカスタム要約を、さらに見栄え良く整えてみましょう:
from great_tables import GT, md
numeric = df.select_dtypes("number")
stats = (numeric.agg(["mean", "median", "std", "min", "max"]).T
.rename_axis("measurement").reset_index())
stats["missing_pct"] = df[numeric.columns].isna().mean().mul(100).values
table = (
GT(stats, rowname_col="measurement")
.tab_header(title="ペンギンの体測定値",
subtitle="記述統計、パーマー諸島)")
.fmt_number(columns=["mean", "median", "std", "min", "max"], decimals=1)
.fmt_percent(columns="missing_pct", decimals=1, scale_values=False)
.data_color(columns="std", palette="Blues")
.tab_source_note(md("出典:*palmerpenguins* データセット (Horst et al.)"))
)
ここではいくつかの処理が行われています。fmt_number と fmt_percent は表示形式を扱うため、手動で丸めを行う必要がなくなります。data_color は std 列に色グラデートを適用し、最も変動の大きい測定値に視線を集めます。tab_header と tab_source_note は、表を完成させたように見せるためのタイトルと出典情報を追加します。さらに、カラムスパンナーや条件付きスタイル、インラインスパークラインなど、できることはたくさんありますが、これだけでもステークホルダーに提示するのに十分なものが作れます。
結果を使用するには、HTML 文字列としてレンダリングします(どこでも動作し、追加の依存関係は不要):
html = table.as_raw_html()
with open("summary_table.html", "w") as f:
f.write(html)
image**
スタイル付けされた Great Tables の出力
# 結び:一度関数化すれば、毎回使える
自動化の目的は反復可能性にあります。パイプラインをラップして、次のデータセットでも単一の呼び出しで済むようにします:
from great_tables import GT, md
def descriptive_report(df, decimals=1):
numeric = df.select_dtypes("number")
stats = (numeric.agg(["count", "mean", "median", "std", "min", "max"]).T
.rename_axis("variable").reset_index())
stats["missing_%"] = df[numeric.columns].isna().mean().mul(100).values
return (
GT(stats, rowname_col="variable")
.tab_header(title="Descriptive Statistics",
subtitle=f"{len(df):,} rows x {df.shape[1]} columns")
.fmt_integer(columns="count")
.fmt_number(columns=["mean", "median", "std", "min", "max"], decimals=decimals)
.fmt_percent(columns="missing_%", decimals=1, scale_values=False)
.data_color(columns="std", palette="Blues")
.tab_source_note(md("Generated automatically with pandas + Great Tables."))
)
descriptive_report(df) # point it at any DataFrame
That's the difference between a snippet and a tool: you write it once and reuse it on every dataset that lands on your desk.
# Wrapping Up
Descriptive statistics don't have to be a chore you re-implement on every project. The ladder we climbed has a rung for every situation:
- Pandas describe() と .agg(): 依存関係ゼロ、クイックチェックやカスタム要約に最適。
- skimpy: 1 つの呼び出しでヒストグラムと欠損データ割合を含む、より豊富なコンソールサマリーを提供。
- fg-data-profiling: 包括的な探索的データ分析(EDA)の全体像が必要な場合に、完全なインタラクティブ HTML レポートを生成。
- tableone: 研究論文向けに層別化された「Table 1」を作成し、p 値と標準化平均差(SMDs)を含め、LaTeX、HTML、CSV へのワンラインエクスポートが可能。
- Great Tables: 作成したあらゆる要約に対して、洗練された出版品質のスタイリングを提供。
質問に答える最も軽量なツールを選びましょう。5 秒で Sanity Check を行うなら describe() が勝利します。論文用なら tableone と Great Tables がその価値を発揮します。そして、お気に入りの組み合わせを関数としてラップすれば、記述統計を「実行する」のではなく「走らせる」ことができるようになります — これがまさに目指すべき状態であり、脳を使う必要がある分析に時間を割くためです。
Kanwal Mehreen は、データサイエンスと AI と医療の交差点に深い情熱を持つ機械学習エンジニアであり技術ライターです。彼女は「ChatGPT で生産性を最大化する」という電子書籍の共著者でもあります。APAC 地域の Google Generation Scholar 2022 として、多様性と学術的卓越性を提唱しています。また、Teradata Diversity in Tech Scholar、Mitacs Globalink Research Scholar、Harvard WeCode Scholar としても認定されています。Kanwal は変革の熱心な支持者であり、STEM 分野における女性のエンパワーメントを目的とした FEMCodes を設立しました。
関連記事
今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み