Python Pandas入門:describe() でデータの特徴(平均・標準偏差・四分位数)を掴む方法

こんにちは。前回は、Pandas DataFrameの全体像を把握するために、head(), tail(), shape, info(), dtypesといった基本的な情報を確認する方法を学びましたね。これらによって、データの大きさや各列のデータ型、欠損値の有無などを知ることができました。

データと「顔見知り」になれたところで、今回はもう一歩踏み込んで、データの中身、特に数値データがどのような特徴を持っているのかを、統計的な観点から要約して見ていきましょう。

今回の主役は、Pandas DataFrameのdescribe()メソッドです。このメソッドを使うことで、複雑な計算をすることなく、データの基本的な統計情報を簡単に確認できます。

この記事を読むことで、あなたは以下のことができるようになります。

  • Pandasのdescribe()メソッドの基本的な使い方を理解する。
  • 数値データに対してdescribe()を実行した際に表示される統計量(平均、標準偏差、最小値、最大値、四分位数など)の意味を、数式を使わずに理解する。
  • 文字列などのカテゴリデータに対してもdescribe()を使い、その種類や最も多い値などを確認する方法を知る。
  • describe()の結果から、データの大まかな傾向や特徴を読み取るヒントを得る。

「統計」と聞くと、数学が苦手な方は少し身構えてしまうかもしれませんが、心配はいりません。describe()が計算してくれる統計量は、データの特徴を掴むための便利な指標です。ここでは、それぞれの指標が「何を表しているのか」という概念的な理解に焦点を当てて、分かりやすく解説していきます。

describe()メソッドとは? なぜ使うの?

describe()メソッドは、DataFrameに含まれるデータの要約統計量を計算して表示してくれる、非常に便利な機能です。要約統計量とは、データの分布や中心的な傾向、ばらつき具合などを代表的な数値で要約したものです。

なぜdescribe()を使うのでしょうか? データ分析を行う際、個々のデータを見るだけでは、データ全体の傾向や特徴を把握するのは難しいことがあります。例えば、「社員の年齢は大体どれくらいか?」「評価スコアは人によってどれくらい差があるのか?」といった疑問に答えるためには、データを集約した情報が必要になります。

describe()を使えば、

  • データの中心的な値(平均値や中央値)
  • データの散らばり具合(標準偏差や最小値・最大値の範囲)
  • データの分布の偏り(平均値と中央値の比較などから推測)
  • 異常な値(外れ値)が存在しないか(最小値や最大値が極端でないか)

などを、一つのコマンドで素早く確認することができます。これは、データクリーニングや可視化、さらには機械学習モデルの構築に進む前の、重要な「データ理解」のステップとなります。

サンプルデータの準備

今回も、前回使用した社員情報のサンプルデータを使って、describe()メソッドの動きを見ていきましょう。まずは、Pandasをインポートし、DataFrameを作成します。既に行った方も、復習として再度実行してみてください。

import pandas as pd

# サンプルデータをPythonの辞書で作る
data = {
    '社員ID': ['S001', 'S002', 'S003', 'S004', 'S005', 'S006', 'S007'],
    '氏名': ['佐藤 一郎', '鈴木 花子', '高橋 健太', '田中 優子', '伊藤 次郎', '渡辺 直美', '山本 翔太'],
    '部署': ['営業部', '開発部', '営業部', '人事部', '開発部', '営業部', '開発部'],
    '年齢': [35, 28, 41, 31, 25, 38, 29],
    '経験年数': [10, 5, 15, 8, 2, 12, 6],
    '評価スコア': [4.5, 4.8, 4.2, 4.0, 4.9, 3.8, 4.6]
}

# 辞書データからDataFrameを作成
df = pd.DataFrame(data)

# 作成したDataFrameを表示(確認用)
print(df)

実行結果(再掲):

  社員ID     氏名   部署  年齢  経験年数  評価スコア
0  S001  佐藤 一郎  営業部  35    10     4.5
1  S002  鈴木 花子  開発部  28     5     4.8
2  S003  高橋 健太  営業部  41    15     4.2
3  S004  田中 優子  人事部  31     8     4.0
4  S005  伊藤 次郎  開発部  25     2     4.9
5  S006  渡辺 直美  営業部  38    12     3.8
6  S007  山本 翔太  開発部  29     6     4.6

このDataFrame df を使って、describe() の機能を学んでいきましょう。

数値データの統計量を確認する (デフォルトのdescribe())

まずは、特別な指定をせずに、シンプルにdescribe()メソッドを実行してみましょう。

使い方:
DataFrame変数(df)の後ろに.describe()とつけて実行します。

# DataFrameの要約統計量を表示
df.describe()

実行結果:

             年齢      経験年数      評価スコア
count   7.000000   7.000000   7.000000
mean   32.428571   8.285714   4.400000
std     5.994045   4.535573   0.391617
min    25.000000   2.000000   3.800000
25%    28.500000   5.500000   4.100000
50%    31.000000   8.000000   4.500000
75%    36.500000  11.000000   4.700000
max    41.000000  15.000000   4.900000

実行結果として、新しい表が表示されました。よく見ると、元のDataFrameにあった列のうち、数値データを持つ列(年齢, 経験年数, 評価スコア)だけが対象となっていることが分かります。describe()は、デフォルトでは数値列の統計量を計算します。

では、行(インデックス)に表示されている各統計量の意味を、一つずつ見ていきましょう。

  • count: その列に含まれる、欠損値ではないデータの個数です。前回学んだinfo()メソッドのNon-Null Countと同じ値になりますね。ここでは全ての数値列で7.0となっており、7人分のデータが全て揃っていることが分かります。
  • mean: 平均値です。いわゆる「平均」のことで、全ての値を合計し、データの個数(count)で割ったものです。データの中心的な傾向を表す最も一般的な指標です。
    • 例:年齢の平均は約32.4歳、評価スコアの平均は4.4点であることが分かります。
  • std: 標準偏差 (Standard Deviation) です。これはデータのばらつき具合を示す指標です。値が大きいほど、データが平均値から広く散らばっている(個人差が大きい)ことを意味し、値が小さいほど、データが平均値の周りに集まっている(個人差が小さい)ことを意味します。
    • 数学的な定義は少し複雑ですが、「各データが平均値からどれくらい離れているか、その平均的な度合い」とイメージすると良いでしょう。
    • 例:年齢の標準偏差は約6.0、評価スコアの標準偏差は約0.39です。単純比較はできませんが、年齢の方が評価スコアよりも(相対的に)ばらつきが大きいのかもしれない、と推測できます。
  • min: 最小値 (Minimum) です。その列の中で最も小さい値を示します。
    • 例:最も若い社員は25歳、経験年数が最も短いのは2年、評価スコアの最低点は3.8点です。
  • 25%: 第1四分位数 (First Quartile) です。データを小さい順に並べたときに、下から25%の位置にある値を示します。言い換えると、全データの小さい方から1/4番目の値です。
    • 四分位数は、データを大きさ順に並べて4等分したときの区切りの値と考えると分かりやすいです。第1四分位数は、最初の区切り点です。
    • 例:年齢の第1四分位数は28.5歳です。これは、全社員の約25%が28.5歳以下であることを意味します。
  • 50%: 第2四分位数 (Second Quartile) であり、これは中央値 (Median) とも呼ばれます。データを小さい順に並べたときに、ちょうど真ん中(50%の位置)にある値を示します。
    • データ数が奇数個の場合は真ん中の値、偶数個の場合は真ん中の2つの値の平均になります。
    • 平均値(mean)は極端に大きい値や小さい値(外れ値)の影響を受けやすいですが、中央値(50%)はその影響を受けにくいという特徴があります。平均値と中央値が大きく異なる場合、データが偏っている(左右対称ではない)可能性があります。
    • 例:年齢の中央値は31歳です。平均値(32.4歳)と比較的近いですね。
  • 75%: 第3四分位数 (Third Quartile) です。データを小さい順に並べたときに、下から75%の位置にある値を示します。全データの大きい方から1/4番目の値、あるいは4等分したときの3番目の区切り点です。
    • 例:経験年数の第3四分位数は11年です。全社員の約75%が経験年数11年以下(逆に言えば、上位25%が11年以上)であることを意味します。
    • 第1四分位数(25%)から第3四分位数(75%)までの範囲を四分位範囲(IQR)と呼び、データのばらつきを見る指標としても使われます(中央の50%のデータがこの範囲に収まります)。
  • max: 最大値 (Maximum) です。その列の中で最も大きい値を示します。
    • 例:最も年齢が高い社員は41歳、経験年数が最も長いのは15年、評価スコアの最高点は4.9点です。

このように、describe()を使うだけで、各数値列の「だいたいどのあたりにデータが集まっているのか(平均値、中央値)」「どのくらい広がっているのか(標準偏差、最小値、最大値、四分位数)」といった特徴を、まとめて把握することができます。特に、min, max, mean, std, そして四分位数(25%, 50%, 75%)は、データの大まかな分布を知る上で非常に役立ちます。

カテゴリデータの統計量を確認する (describe(include='object'))

デフォルトのdescribe()は数値データのみを対象としましたが、文字列などの**カテゴリデータ**(質的データとも呼ばれます)についても、基本的な情報を要約したい場合があります。例えば、「部署は何種類あるか?」「どの部署が一番多いか?」などを知りたいときです。

このような場合は、describe()メソッドにincludeという引数(オプション)を指定します。カテゴリデータ(多くの場合、Pandasではobject型として扱われます)の統計量を見たい場合は、include='object'と指定します。

使い方:
describe()の括弧の中に、include='object'と書きます。

# カテゴリデータ(object型)の要約統計量を表示
df.describe(include='object')

実行結果:

        社員ID    氏名   部署
count      7     7    7
unique     7     7    3
top     S001  佐藤 一郎  営業部
freq       1     1    3

今度は、元のDataFrameのobject型であった社員ID, 氏名, 部署列に関する統計量が表示されました。数値データのときとは異なる統計量が表示されていますね。それぞれの意味を見てみましょう。

  • count: こちらもデータの個数(欠損値を除く)です。数値データのときと同じですね。
  • unique: その列に含まれる、ユニークな値(異なる値)の種類数です。
    • 例:社員ID氏名は7種類あり、全員異なるIDと氏名を持っていることが分かります。部署は3種類(’営業部’, ‘開発部’, ‘人事部’)であることが分かります。
  • top: その列で最も頻繁に出現する値(最頻値)です。一番メジャーなカテゴリを示します。
    • 例:部署列のtop営業部です。つまり、この会社(のサンプルデータ)では営業部が最も多い部署であることが分かります。社員ID氏名は全てユニークなので、topには最初に出てきた値が表示されています(この場合はあまり意味がありません)。
  • freq: topで示された値(最頻値)が、その列に何回出現したか(頻度)を示します。
    • 例:部署列のfreq3です。これは、topである営業部が3回出現したことを意味します(7人中3人が営業部所属)。

このように、include='object'を指定することで、カテゴリデータの種類や最頻値などを簡単に確認できます。これは、データの構成を理解する上で役立ちます。

すべての列の統計量をまとめて表示する (describe(include='all'))

数値データとカテゴリデータの統計量を別々に見る方法を学びましたが、場合によっては、全ての列に関する情報を一度に表示したいこともあるかもしれません。そのような場合は、include引数に'all'を指定します。

使い方:
describe()の括弧の中に、include='all'と書きます。

# 全ての列の要約統計量を表示
df.describe(include='all')

実行結果:

         社員ID     氏名   部署         年齢      経験年数      評価スコア
count        7      7    7   7.000000   7.000000   7.000000
unique       7      7    3        NaN        NaN        NaN
top       S001  佐藤 一郎  営業部        NaN        NaN        NaN
freq         1      1    3        NaN        NaN        NaN
mean       NaN    NaN  NaN  32.428571   8.285714   4.400000
std        NaN    NaN  NaN   5.994045   4.535573   0.391617
min        NaN    NaN  NaN  25.000000   2.000000   3.800000
25%        NaN    NaN  NaN  28.500000   5.500000   4.100000
50%        NaN    NaN  NaN  31.000000   8.000000   4.500000
75%        NaN    NaN  NaN  36.500000  11.000000   4.700000
max        NaN    NaN  NaN  41.000000  15.000000   4.900000

全ての列(社員IDから評価スコアまで)が表示されました。ただし、よく見るとNaNという表示がたくさんありますね。

NaNは「Not a Number」の略で、数値ではない、あるいは計算できないことを意味します。

  • 社員ID, 氏名, 部署といったカテゴリ列(object型)に対して、平均値(mean)や標準偏差(std)などを計算することは意味がないため、NaNと表示されています。
  • 逆に、年齢, 経験年数, 評価スコアといった数値列に対して、ユニークな値の種類数(unique)や最頻値(top)、その頻度(freq)を計算することは、通常あまり意味がない(またはdescribeのデフォルトの対象ではない)ため、こちらもNaNと表示されています。

include='all'は、数値列とカテゴリ列で計算できる統計量が異なることを念頭に置いた上で、データ全体の概要を一目で確認したい場合に便利です。

まとめ

今回は、Pandas DataFrameのdescribe()メソッドを使って、データの基本的な統計情報を要約する方法を学びました。

  • describe()は、データの大まかな特徴(中心的な値、ばらつき具合など)を素早く把握するための強力なツールです。
  • デフォルトでは数値データの統計量(count, mean, std, min, 25%, 50%, 75%, max)を表示します。
  • 各統計量の意味を、数式を使わずに概念的に理解しました。特に、平均(mean)、標準偏差(std)、中央値(50%)、最小/最大値(min/max)はデータの傾向を掴む上で重要です。
  • include='object'オプションを使うことで、カテゴリデータの統計量(count, unique, top, freq)を表示できます。これにより、データの種類や最頻値を確認できます。
  • include='all'オプションを使うことで、すべての列の統計量を可能な範囲でまとめて表示できますが、計算できない箇所はNaNと表示されます。

describe()メソッドは、head()info()などと並んで、データ分析の初期段階で「まず実行してみる」べきコマンドの一つです。これらの情報を組み合わせることで、手元にあるデータがどのようなものなのか、より深く理解することができるようになります。

次回予告

今回はデータ全体の統計的な特徴を見る方法を学びました。しかし、実際の分析では、「営業部の社員だけの平均年齢を知りたい」「評価スコアが4.5以上の人だけをリストアップしたい」といったように、特定の条件に合うデータだけを取り出して操作したい場面が多くあります。

次回は、DataFrameの中から、条件を指定して必要な「行」や「列」だけを選択(フィルタリング、スライシング)する方法について、具体的なコードとともに詳しく解説していきます。データの絞り込みができるようになると、分析の自由度が格段に上がりますよ。お楽しみに!