df.describe()を実行できても、count、mean、std、25%、50%をどう読めばよいのか迷うことはありませんか。
describe()は、DataFrameの各列について、データの中心・ばらつき・範囲をまとめて確認するメソッドです。結果は、まず count、次に mean と 50%、その後に std、min・25%・75%・max の順で読むと理解しやすくなります。
この記事では、売上データを使って、pandas describe()の基本と結果の読み方を解説します。読み終えると、欠損、値の偏り、ばらつき、極端な値の候補に気づき、次の処理を選べるようになります。
- この記事でわかること
- 先に結論:describe()は値の分布をまとめて確認するときに使う
- 売上データを用意する
- df.describe()の基本的な使い方
- describe()の結果は4段階で読む
- 大きな値が平均値に与える影響を比較する
- 数値列以外をdescribe()で確認する
- percentilesで表示する分位点を変更する
- Series.describe()とDataFrame.describe()の違い
- describe()と個別メソッドの使い分け
- コードは動くが結果を誤解しやすい5つの場面
- データ分析では「実データ→構造→分布→次の処理」の順で使う
- まとめ:describe()は結果を読んで次の処理を決めるために使う
- 関連記事
この記事でわかること
-
df.describe()の基本的な使い方 - 各統計量の意味と読む順序
- describe()の結果を読む順序
- 数値列・文字列列・日付列で出力が変わる理由
-
include='all'とpercentilesの基本 - describe()・head()・info()の使い分け
- 結果を欠損処理、型変換、可視化へつなげる方法
この記事は、データを読み込んだ後に内容を確認する段階の記事です。DataFrameの基本はPandas DataFrame入門、データの取り込みはGoogle ColabでCSVを読み込む方法で確認できます。
先に結論:describe()は値の分布をまとめて確認するときに使う
describe()を使う目的は、単に統計量を表示することではありません。列ごとの件数、中心、ばらつき、範囲を短い表で確認し、次の作業を決めることです。
データを読み込んだ直後は、次のように使い分けます。
| 機能名 | 何を確認するか | 選ぶ場面 | 注意点 |
|---|---|---|---|
head() |
先頭の実データ | 列名や値の入り方を目で見る | 先頭だけで全体を判断しない |
info() |
行数、列名、データ型、非欠損数 | DataFrameの構造を確認する | 値の分布は分からない |
dtypes |
各列のデータ型 | 型だけをすばやく確認する | 欠損数や値の分布は分からない |
describe() |
件数、中心、ばらつき、範囲 | 数値の分布をまとめて確認する | 初期設定では通常、数値列が対象 |
迷ったら、head()で実データ → info()で構造 → describe()で分布の順に確認します。head()については、pandas head()の使い方で詳しく解説しています。
売上データを用意する
日付・店舗・売上・客数を含むDataFrameを作ります。売上には、欠損値1つと、ほかの日より大きい500という値を入れています。
import pandas as pd
import numpy as np
df = pd.DataFrame({
"日付": pd.to_datetime([
"2026-08-01", "2026-08-02", "2026-08-03", "2026-08-04",
"2026-08-05", "2026-08-06", "2026-08-07", "2026-08-08"
]),
"店舗": ["東京", "大阪", "東京", "大阪", "東京", "大阪", "東京", "大阪"],
"売上": [100, 120, 110, np.nan, 130, 125, 500, 115],
"客数": [10, 12, 11, 13, 13, 12, 14, 11]
})
df
| 日付 | 店舗 | 売上 | 客数 | |
|---|---|---|---|---|
| 0 | 2026-08-01 | 東京 | 100 | 10 |
| 1 | 2026-08-02 | 大阪 | 120 | 12 |
| 2 | 2026-08-03 | 東京 | 110 | 11 |
| 3 | 2026-08-04 | 大阪 | NaN | 13 |
| 4 | 2026-08-05 | 東京 | 130 | 13 |
| 5 | 2026-08-06 | 大阪 | 125 | 12 |
| 6 | 2026-08-07 | 東京 | 500 | 14 |
| 7 | 2026-08-08 | 大阪 | 115 | 11 |
表示された元データは8行です。売上列の4行目には NaN があり、7行目の売上は500です。ここでは NaN を0円という意味にはせず、売上の値が記録されていない状態として扱います。
数字に見える列でも、文字列型なら標準のdescribe()では数値列として集計されません。自分のデータでは、列名、行数、欠損値、データ型を先に確認しましょう。
df.describe()の基本的な使い方
DataFrameに .describe() を付けると、初期設定では数値列の要約統計量が返されます。describe()は元のDataFrameを書き換えません。
summary = df.describe()
summary
| 日付 | 売上 | 客数 | |
|---|---|---|---|
| count | 8 | 7 | 8 |
| mean | 2026-08-04 12:00:00 | 171.428571 | 12 |
| min | 2026-08-01 00:00:00 | 100 | 10 |
| 25% | 2026-08-02 18:00:00 | 112.5 | 11 |
| 50% | 2026-08-04 12:00:00 | 120 | 12 |
| 75% | 2026-08-06 06:00:00 | 127.5 | 13 |
| max | 2026-08-08 00:00:00 | 500 | 14 |
| std | NaN | 145.221506 | 1.309307 |
この結果では、数値列である売上と客数が表示されます。注目したい点は次のとおりです。
- 元データは8行ですが、
売上のcountは7です。欠損値1件が計算から除かれています。 -
客数には欠損値がないため、countは8です。 -
売上のmeanは50%よりかなり大きくなります。売上500の影響を受けている可能性があります。 -
日付と店舗は、初期設定の結果には表示されません。
このように、最初の出力だけでも欠損と大きな値の候補に気づけます。describe()の結果はDataFrameとして変数に保存できます。
describe()の結果は4段階で読む
数値列の出力は、次の順序で読むと判断につなげやすくなります。
| 読む順序 | 項目 | 意味 | 確認すること |
|---|---|---|---|
| 1 | count |
欠損値を除いた件数 | 元の行数より少なくないか |
| 2 |
mean・50%
|
平均値・中央値 | 2つが大きく離れていないか |
| 3 | std |
標準偏差 | 値のばらつきが大きそうか |
| 4 |
min・25%・75%・max
|
最小値・四分位数・最大値 | 値の範囲や極端な値の候補がないか |
この順番なら、欠損の見落としを防ぎ、平均値だけに頼らず、分布全体を確認できます。
count:欠損値を除いた件数
countは、各列の欠損していない値の数です。DataFrame全体の行数とは限りません。
元の行数とcountを並べると、何が違うかを追いやすくなります。
count_comparison = pd.DataFrame({
"確認対象": ["DataFrame全体", "売上", "客数"],
"件数": [len(df), df["売上"].count(), df["客数"].count()],
"何を数えたか": ["すべての行", "売上の非欠損値", "客数の非欠損値"]
})
count_comparison
| 確認対象 | 件数 | 何を数えたか | |
|---|---|---|---|
| 0 | DataFrame全体 | 8 | すべての行 |
| 1 | 売上 | 7 | 売上の非欠損値 |
| 2 | 客数 | 8 | 客数の非欠損値 |
DataFrame全体は8行ですが、売上は7件です。この差から、売上に欠損値が1件あると気づけます。欠損箇所を詳しく調べる場合は、Pandas isnull()で欠損値を確認する方法へ進みます。
欠損値を埋めるかどうかはデータの意味によって決めます。機械的に0や平均値で埋めるのではなく、pandas fillna()の使い方を参考に、欠損した理由を確認してください。
meanと50%:平均値と中央値を比べる
meanは平均値、50%は中央値です。中央値は、値を小さい順に並べたときの中央を表します。
平均値と中央値が離れているときは、一部の大きな値や小さな値に平均が引っ張られていないか確認します。売上列から2つの値を取り出して比べてみましょう。
df["売上"].describe().loc[["mean", "50%"]]
| 売上 | |
|---|---|
| mean | 171.428571 |
| 50% | 120 |
このデータでは平均値が中央値より大きくなります。原因の候補は売上500です。ただし、500が入力ミスとは限りません。キャンペーンなどで実際に売上が増えた可能性もあるため、describe()だけで削除を決めず、元データや業務上の理由を確認します。
std:値のばらつきを確認する
stdは標準偏差で、値が平均の周りにどの程度ばらついているかを表す指標です。同じ単位のデータなら、一般にstdが大きいほど値の散らばりも大きいと考えられます。
ただし、stdの大きさだけを見て「異常」とは判断できません。売上と客数のように単位や値の規模が違う列同士では、数値をそのまま比較しないようにします。標準偏差の数式や推測統計にはここでは深入りせず、分布を確認する目安として使います。
min・25%・50%・75%・max:値の範囲と中央部分を見る
minとmaxは最小値と最大値です。25%、50%、75%は分位点で、初期設定では第1四分位数、中央値、第3四分位数が表示されます。
25%は「値を25%にする処理」ではありません。データを小さい順に見たとき、下位25%の境目となる値です。25%から75%を見ると、データ中央の50%がどの範囲にあるか分かります。
今回の売上では、中央部分の値に対してmaxが離れています。この差は詳しく確認するきっかけになりますが、describe()だけで外れ値と断定はできません。分布の形を確かめる場合は、Matplotlibのヒストグラム・箱ひげ図につなげます。
大きな値が平均値に与える影響を比較する
「平均値と中央値が離れる」とはどういうことかを、条件をそろえた2つの売上データで確認します。通常範囲の7個の値と、その最後の値だけを500へ変えたデータを比較します。
sales_typical = pd.Series([100, 120, 110, 125, 130, 115, 105], name="通常範囲")
sales_with_large_value = pd.Series([100, 120, 110, 125, 130, 115, 500], name="大きな値を含む")
comparison = pd.concat(
[sales_typical.describe(), sales_with_large_value.describe()],
axis=1
).loc[["count", "mean", "std", "min", "25%", "50%", "75%", "max"]]
comparison
| 通常範囲 | 大きな値を含む | |
|---|---|---|
| count | 7 | 7 |
| mean | 115 | 171.428571 |
| std | 10.801234 | 145.221506 |
| min | 100 | 100 |
| 25% | 107.5 | 112.5 |
| 50% | 115 | 120 |
| 75% | 122.5 | 127.5 |
| max | 130 | 500 |
両方ともcountは7ですが、大きな値を含むデータではmeanとstdが大きくなります。一方、50%は中央の順位で決まるため、平均値ほど大きな影響を受けません。
この比較から、次のように判断できます。
| データの状態 | meanと50% | std | 次に確認すること |
|---|---|---|---|
| 値が比較的まとまっている | 近くなりやすい | 比較的小さい | 通常の分布として妥当か |
| 大きな値を含む | meanが50%より大きくなりやすい | 大きくなりやすい | 入力ミスか、意味のある実績か |
これは「コードは正しく動いているのに、平均値だけを代表値だと思うと結果を誤解しやすい」例です。meanだけでなく50%、std、maxを組み合わせて読みます。
数値列以外をdescribe()で確認する
文字列列ではunique・top・freqが表示される
初期設定のdf.describe()は、数値列を含むDataFrameでは通常、数値列を対象にします。店舗のような文字列列を確認したい場合は、対象列を選んでdescribe()を使います。
df["店舗"].describe()
| 店舗 | |
|---|---|
| count | 8 |
| unique | 2 |
| top | 東京 |
| freq | 4 |
文字列列では、数値列とは異なる項目が表示されます。
| 項目 | 文字列列での意味 |
|---|---|
count |
欠損値を除いた件数 |
unique |
異なる値の種類数 |
top |
最も多く現れる値の1つ |
freq |
topが現れた回数 |
今回の店舗は東京と大阪の2種類です。出現回数が同数のように、最頻値が複数ある場合、topだけを見て特定の値が必ず選ばれると考えないでください。公式仕様では、同数の候補から任意の1つが表示されます。
include=’all’ですべての列を確認する
数値列、文字列列、日付列をまとめて対象にするには、include='all'を指定します。
df.describe(include="all")
| 日付 | 店舗 | 売上 | 客数 | |
|---|---|---|---|---|
| count | 8 | 8 | 7 | 8 |
| unique | NaN | 2 | NaN | NaN |
| top | NaN | 東京 | NaN | NaN |
| freq | NaN | 4 | NaN | NaN |
| mean | 2026-08-04 12:00:00 | NaN | 171.428571 | 12 |
| min | 2026-08-01 00:00:00 | NaN | 100 | 10 |
| 25% | 2026-08-02 18:00:00 | NaN | 112.5 | 11 |
| 50% | 2026-08-04 12:00:00 | NaN | 120 | 12 |
| 75% | 2026-08-06 06:00:00 | NaN | 127.5 | 13 |
| max | 2026-08-08 00:00:00 | NaN | 500 | 14 |
| std | NaN | NaN | 145.221506 | 1.309307 |
列の種類によって計算できる統計量が違うため、表には多数のNaNが表示される場合があります。
このNaNは、必ずしも元データの欠損ではありません。たとえば文字列列では平均値を計算できないため、その欄がNaNになります。
日付列はpandasのバージョンや列のデータ型を確認しながら結果を読みます。今回のようなdatetime型では、件数や日付範囲などの要約が表示されます。日付が文字列のままだと期待した結果にならないため、必要ならpandas to_datetime()の使い方で変換します。
includeで確認するデータ型を選ぶ
特定の型だけを確認したい場合は、includeに対象を指定します。数値列だけならnumber、文字列として格納された列ならobjectなどを使えます。
# pandasのバージョンや読み込み方法によって、
# 文字列列はobject型またはstring型になることがあります
df.dtypes
| 日付 | datetime64[ns] |
| 店舗 | object |
| 売上 | float64 |
| 客数 | int64 |
文字列列は、pandasのバージョンや読み込み方法によってobject型またはstring型になります。objectと決めつけず、先に実際の型を確認します。
numeric_summary = df.describe(include="number")
string_columns = df.select_dtypes(include=["object", "string"]).columns
string_summary = df[string_columns].describe()
numeric_summary, string_summary
| 売上 | 客数 | |
|---|---|---|
| count | 7 | 8 |
| mean | 171.428571 | 12 |
| std | 145.221506 | 1.309307 |
| min | 100 | 10 |
| 25% | 112.5 | 11 |
| 50% | 120 | 12 |
| 75% | 127.5 | 13 |
| max | 500 | 14 |
| 店舗 | |
|---|---|
| count | 8 |
| unique | 2 |
| top | 東京 |
| freq | 4 |
numeric_summaryには売上と客数、string_summaryには店舗が表示されます。objectとstringの両方を候補にして、環境による文字列型の違いへ対応しています。
対象列が選ばれないときはdf.dtypesを確認してください。型による列抽出はpandas select_dtypes()の使い方、数字の文字列を変換する方法はpandas to_numeric()の使い方で解説しています。
percentilesで表示する分位点を変更する
percentilesを指定すると、初期設定の25%・50%・75%以外の分位点を表示できます。値は0から1の範囲で指定します。ここでは10%と90%を追加して確認します。
df["売上"].describe(percentiles=[0.1, 0.25, 0.5, 0.75, 0.9])
| 売上 | |
|---|---|
| count | 7 |
| mean | 171.428571 |
| std | 145.221506 |
| min | 100 |
| 10% | 106 |
| 25% | 112.5 |
| 50% | 120 |
| 75% | 127.5 |
| 90% | 278 |
| max | 500 |
10%や90%を追加すると、分布の端に近い部分をもう少し細かく確認できます。ただし、データが7件しかない今回の例では、細かな分位点を過度に解釈しないことが重要です。まずは初期設定の25%・50%・75%を読めれば十分です。
Series.describe()とDataFrame.describe()の違い
1列を選んでdescribe()を使うとSeriesが返り、複数列を含むDataFrameへ使うとDataFrameが返ります。
series_result = df["売上"].describe()
dataframe_result = df[["売上", "客数"]].describe()
print(type(series_result))
print(type(dataframe_result))
<class 'pandas.core.series.Series'> <class 'pandas.core.frame.DataFrame'>
1列だけ詳しく読みたいならSeries、複数の数値列を同じ表で比べたいならDataFrameが便利です。なお、DataFrame用のincludeとexcludeはSeriesでは無視されます。
describe()と個別メソッドの使い分け
describe()は複数の統計量をまとめて確認する入口です。特定の値だけが必要なら個別メソッドを使います。
| 機能名 | 何を求めるか | 選ぶ場面 | 注意点 |
|---|---|---|---|
describe() |
複数の要約統計量 | 最初に分布の全体像を確認する | 初期設定では通常、数値列が対象 |
mean() |
平均値 | 平均だけを計算に使う | 大きな値・小さな値の影響を受ける |
std() |
標準偏差 | ばらつきだけを確認する | 単位や値の規模も考慮する |
quantile() |
指定した分位点 | 任意の分位点を個別に求める | 0から1の位置を指定する |
最初はdescribe()で全体を見て、必要な統計量が決まった後に個別メソッドを選ぶと、確認漏れを減らせます。
コードは動くが結果を誤解しやすい5つの場面
| 症状 | 主な原因 | 確認方法 | 修正・判断方法 |
|---|---|---|---|
| countが行数より少ない | 欠損値がある |
len(df)とcountを比較 |
欠損箇所と理由を確認する |
| 数字の列が表示されない | 数字が文字列型になっている |
df.dtypesを確認 |
必要ならto_numeric()などで変換 |
| 文字列列が表示されない | 初期設定では数値列が優先される | 列の型と対象列を確認 | 列を選ぶかincludeを指定 |
include='all'でNaNが多い |
その型に適用できない統計量がある | 元データと出力表を分けて確認 | 欠損値と「計算対象外」を区別 |
| meanが代表値として不自然 | 一部の極端な値に引っ張られた | meanと50%・maxを比較 | 元データと分布を確認する |
describe()はエラーを出さずに結果を返すことが多いため、動いたことと、正しく解釈できたことは別です。
データ分析では「実データ→構造→分布→次の処理」の順で使う
describe()は、データ分析の「確認」段階で使います。次の順序にすると、結果を表示するだけで終わりません。
-
head()で列名と実際の値を見る -
info()やdtypesで型と非欠損数を確認する -
describe()で件数、中心、ばらつき、範囲を読む - 問題に応じて欠損処理や型変換を行う
- ヒストグラムや箱ひげ図で分布を可視化する
- 必要に応じて列同士の関係を確認する
列同士の関係を調べる段階では、pandas corr()の使い方へ進めます。ただし、describe()は各列の分布、corr()は列と列の関係を見るメソッドであり、役割が異なります。
自分のデータへ置き換えるときは、次の点を確認してください。
- countは元の行数と一致しているか
- 集計したい列は数値型になっているか
- meanと50%が大きく離れていないか
- min・maxは現実的な値か
- 単位の違う列のstdを単純比較していないか
-
include='all'のNaNを元データの欠損と混同していないか
まとめ:describe()は結果を読んで次の処理を決めるために使う
-
describe()は、列の件数・中心・ばらつき・範囲をまとめて確認する - 結果は
count→meanと50%→std→四分位数とmin・maxの順で読む -
countは欠損値を除いた件数で、DataFrameの行数とは限らない -
50%は平均値ではなく中央値 - meanと50%の差は、値の偏りや極端な値へ気づく手がかりになる
-
stdはばらつきの目安だが、単位や値の規模も踏まえて判断する - 文字列列では
unique・top・freqなどが表示される -
include='all'のNaNは、元データの欠損ではなく、その型に統計量を適用できない場合もある - 実データはhead()、構造はinfo()、分布はdescribe()で確認する
- describe()の結果に応じて、欠損処理、型変換、可視化へ進む
describe()の表を表示できたら、平均値だけを見るのではなく、複数の項目を組み合わせて読むことが大切です。
関連記事
- Pandas DataFrame入門|作り方と基本操作を初心者向けに解説
- pandas head()の使い方|df.head()で先頭5行を表示・tail()との違いも解説
- Google ColabでCSVを読み込む方法|アップロード・Drive・read_csv
- pandas select_dtypes()の使い方|データ型で列を選ぶ方法
- pandas to_numeric()の使い方|文字列の数字を数値に変換する方法
- pandas astype()の使い方|文字列・整数・小数の型変換とエラー対処
- pandas fillna()の使い方|欠損値を埋める方法
- 欠損値を可視化して攻略!Pandas isnullとヒートマップ活用術
- Matplotlib ヒストグラム&箱ひげ図 入門
- pandas corr()の使い方|相関係数・相関行列を初心者向けに解説
- pandas.DataFrame.describe公式ドキュメント
pandasのdescribe()は何をするメソッドですか?
DataFrameやSeriesの記述統計量をまとめて返すメソッドです。数値列では件数、平均値、標準偏差、最小値、四分位数、最大値などを確認できます。
countはDataFrameの行数と同じですか?
必ずしも同じではありません。describe()のcountは、その列の欠損していない値を数えます。元データが8行でも欠損値が1件あれば、その列のcountは7です。
50%は平均値ですか?
いいえ。50%は中央値です。平均値はmeanに表示されます。meanと50%が大きく離れている場合は、一部の大きな値や小さな値の影響を確認します。
数値列しか表示されないのはなぜですか?
数値列を含むDataFrameに引数なしでdescribe()を使うと、初期設定では数値列が対象になるためです。文字列列は列を個別に選ぶか、include='object'やinclude='all'などを目的に応じて指定します。
include=’all’でNaNが表示されるのは異常ですか?
異常とは限りません。数値列のuniqueや文字列列のmeanのように、そのデータ型には適用されない統計量がNaNになる場合があります。元データの欠損値とは分けて考えます。
describe()とinfo()の違いは何ですか?
describe()は値の分布を要約し、info()は行数、列名、データ型、非欠損数などDataFrameの構造を表示します。データを読み込んだ直後は両方を使うと役割を補い合えます。
標準偏差が大きいとはどういう意味ですか?
一般には、値が平均の周りに広く散らばっていることを示します。ただし、大きさはデータの単位や規模にも左右されるため、単位の異なる列同士を数値だけで比較しないでください。
describe()だけで外れ値を判断できますか?
describe()は、maxと四分位数が大きく離れているなど、極端な値の候補に気づく入口です。入力ミスか意味のある値かは、元データ、業務上の理由、ヒストグラムや箱ひげ図も確認して判断します。
コメント