pandasのdescribeで各列の要約統計量(平均、標準偏差など)を取得

pandas.DataFrameおよびpandas.Seriesのメソッドdescribe()を使うと、各列ごとに平均や標準偏差、最大値、最小値、最頻値などの要約統計量を取得できます。 とりあえずデータの雰囲気をつかむのにとても便利。

pandas.DataFrame.describe — pandas 0.23.0 documentation

列ごとに異なる型dtypeをもつpandas.DataFrameを例とします。

import pandas as pd

df = pd.DataFrame({'a': [1, 2, 1, 3],
                   'b': [0.4, 1.1, 0.1, 0.8],
                   'c': ['X', 'Y', 'X', 'Z'],
                   'd': ['3', '5', '2', '1'],
                   'e': [True, True, False, True]})

print(df)
#    a    b  c  d      e
# 0  1  0.4  X  3   True
# 1  2  1.1  Y  5   True
# 2  1  0.1  X  2  False
# 3  3  0.8  Z  1   True

print(df.dtypes)
# a      int64
# b    float64
# c     object
# d     object
# e       bool
# dtype: object

pandasの型dtypeについては以下の記事を参照。

ここでは以下の内容について説明します。

describe()の基本的な使い方 対象となる型を指定: 引数include, exclude 文字列など数値以外の列を指定 すべての型の列を指定 任意の型を選択・除外

describe()の項目の意味と対応する個別メソッド パーセンタイルの刻みを指定 数値列に対して頻度などを算出 数字の文字列に対して平均や標準偏差などを算出 pandas.Seriesのdescribe() 日時(datetime64[ns]型)の場合 行に対してdescribe()を適用

describeの基本的な使い方

例のpandas.DataFrameから引数を何も指定せずにdescribe()メソッドを呼ぶと、結果がpandas.DataFrameとして返される。

print(df.describe())
#               a         b
# count  4.000000  4.000000
# mean   1.750000  0.600000
# std    0.957427  0.439697
# min    1.000000  0.100000
# 25%    1.000000  0.325000
# 50%    1.500000  0.600000
# 75%    2.250000  0.875000
# max    3.000000  1.100000

print(type(df.describe()))
# <class 'pandas.core.frame.DataFrame'>

行や要素はlocやatで取得できます。

print(df.describe().loc['std'])
# a    0.957427
# b    0.439697
# Name: std, dtype: float64

print(df.describe().at['std', 'b'])
# 0.439696865275764

様々な型の列が存在するpandas.DataFrameの場合、デフォルトでは数値(整数型int、浮動小数点型float)の列のみが選択され、平均meanや標準偏差stdなどの項目が算出される。項目の意味については後述。 あくまでも型dtypeに基づいた判断なので、例のd列のように数字の文字列の列は除外される。 欠損値NaNがある場合は除外されて算出される。

対象となる型を指定: 引数include, exclude

数値型以外の列に対して要約統計量を取得するには、引数include, excludeを設定します。 includeには結果に含める型、excludeには結果から除外する型を指定します。列名ではなく型を指定するので注意。

文字列など数値以外の列を指定

数値型は'number'で表されるので、exclude='number'とすると、数値以外の文字列型などの列の結果が算出される。

print(df.describe(exclude='number'))
#         c  d     e
# count   4  4     4
# unique  3  4     2
# top     X  3  True
# freq    2  1     3

結果からわかるように、数値とそれ以外では算出される項目が異なる。項目の意味については後述。 なお、もともと数値列が含まれていないpandas.DataFrameの場合は特に引数を設定しなくても問題ありません。

df_notnum = df[['c', 'd', 'e']]
print(df_notnum)
#    c  d      e
# 0  X  3   True
# 1  Y  5   True
# 2  X  2  False
# 3  Z  1   True

print(df_notnum.dtypes)
# c    object
# d    object
# e      bool
# dtype: object

print(df_notnum.describe())
#         c  d     e
# count   4  4     4
# unique  3  4     2
# top     X  3  True
# freq    2  1     3

すべての型の列を指定

include='all'とすると、すべての型の列が対象となります。

print(df.describe(include='all'))
#                a         b    c    d     e
# count   4.000000  4.000000    4    4     4
# unique       NaN       NaN    3    4     2
# top          NaN       NaN    X    3  True
# freq         NaN       NaN    2    1     3
# mean    1.750000  0.600000  NaN  NaN   NaN
# std     0.957427  0.439697  NaN  NaN   NaN
# min     1.000000  0.100000  NaN  NaN   NaN
# 25%     1.000000  0.325000  NaN  NaN   NaN
# 50%     1.500000  0.600000  NaN  NaN   NaN
# 75%     2.250000  0.875000  NaN  NaN   NaN
# max     3.000000  1.100000  NaN  NaN   NaN

ただし、数値列とそれ以外の型の列で算出される項目が異なるため、算出されない項目の値は欠損値NaNとなります。

任意の型を選択・除外

引数include, excludeに任意の型を指定することも可能。結果が一列のみでもpandas.DataFrame型が返る。

print(df.describe(include=int))
#               a
# count  4.000000
# mean   1.750000
# std    0.957427
# min    1.000000
# 25%    1.000000
# 50%    1.500000
# 75%    2.250000
# max    3.000000

print(type(df.describe(include=int)))
# <class 'pandas.core.frame.DataFrame'>

リストで複数の型を指定できます。算出される項目は選択された型によって自動で決まる。

print(df.describe(include=[object, bool]))
#         c  d     e
# count   4  4     4
# unique  3  4     2
# top     X  3  True
# freq    2  1     3

print(df.describe(exclude=[float, object]))
#                a     e
# count   4.000000     4
# unique       NaN     2
# top          NaN  True
# freq         NaN     3
# mean    1.750000   NaN
# std     0.957427   NaN
# min     1.000000   NaN
# 25%     1.000000   NaN
# 50%     1.500000   NaN
# 75%     2.250000   NaN
# max     3.000000   NaN

'number'や'all'は引用符'または"で囲む必要があるが、intやfloatなどPython標準の組み込み型は引用符で囲まずにinclude=intのように指定可能。include='int'でも問題ない。 型dtypeについての詳細は以下の記事を参照。

describeの項目の意味と対応する個別メソッド

describe()で算出される項目の意味と、各項目のみを個別に算出したい場合に使えるメソッドを示す。 describe()で得られるpandas.DataFrameの行をloc[]で指定すれば項目ごとの値を選択できるが、他の項目が必要なければ個別のメソッドを使ったほうが無駄がない。 なお、上述のように、describe()ではいずれの項目を算出する際も欠損値NaNは除いて処理される。 count: 要素の個数 count()メソッドで個別に算出可能。

print(df.count())
# a    4
# b    4
# c    4
# d    4
# e    4
# dtype: int64

unique: ユニークな(一意な)値の要素の個数 nunique()メソッドで個別に算出可能。

print(df.nunique())
# a    3
# b    4
# c    3
# d    4
# e    2
# dtype: int64

top: 最頻値(mode) mode()メソッドで個別に算出可能。

mode()はpandas.DataFrameを返す。頻度が同数の値がある場合は最頻値が複数になり、列ごとに最頻値の個数が異なるので、空き部分は欠損値NaNとなります。

print(df.mode())
#      a    b    c  d     e
# 0  1.0  0.1    X  1  True
# 1  NaN  0.4  NaN  2   NaN
# 2  NaN  0.8  NaN  3   NaN
# 3  NaN  1.1  NaN  5   NaN

各列の最頻値の個数は、mode()の結果に対して欠損値NaNではない要素の個数をカウントするcount()メソッドを適用して取得できます。

print(df.mode().count())
# a    1
# b    4
# c    1
# d    4
# e    1
# dtype: int64

iloc[0]で先頭行を選択すると、各列ごとの最頻値が少なくとも一つずつ取得できます。

print(df.mode().iloc[0])
# a       1
# b     0.1
# c       X
# d       1
# e    True
# Name: 0, dtype: object

describe()の項目topも最頻値が複数ある場合にその中の一つだけを返すが、mode()の先頭行と一致するとは限らないので注意。 freq: 最頻値の頻度(出現回数) pandas.Seriesのvalue_counts()メソッドで個別に算出可能。

value_counts()は、ユニークな要素の値がindex、その頻度(出現回数)がdataとなるpandas.Seriesを返す。 デフォルトでは出現回数が多い順にソートされるので、value_counts()メソッドが返すpandas.Seriesの先頭の値が最頻値の頻度となります。

print(df['c'].value_counts().iat[0])
# 2

pandas.DataFrameの各列の最頻値の頻度を取得したい場合はapply()メソッドで各列にvalue_counts()メソッドの結果から先頭の値を返す無名関数を適用します。

print(df.apply(lambda x: x.value_counts().iat[0]))
# a    2
# b    1
# c    2
# d    1
# e    3
# dtype: int64

value_counts()では元のpandas.Seriesの要素が結果のpandas.Seriesのindexとなります。数値がindexの場合は[番号]で値を指定できない(エラーになる)ためiat[番号]を使って厳密に指定しています。 mean: 算術平均 mean()メソッドで個別に算出可能。 引数numeric_only=Trueとすると数値列のみの結果となります。以下のメソッドでも同じ。

print(df.mean(numeric_only=True))
# a    1.75
# b    0.60
# e    0.75
# dtype: float64

describe()ではbool型の列は除外されるが、mean()ではTrue=1, False=0として扱われる。以下のメソッドでも同じ。 std: 標準偏差 標本標準偏差などと呼ばれる、n-1で割られるもの。 std()メソッドで個別に算出可能。

print(df.std(numeric_only=True))
# a    0.957427
# b    0.439697
# e    0.500000
# dtype: float64

min: 最小値 min()メソッドで個別に算出可能。

print(df.min(numeric_only=True))
# a    1.0
# b    0.1
# e    0.0
# dtype: float64

max: 最大値 max()メソッドで個別に算出可能。

print(df.max(numeric_only=True))
# a    3.0
# b    1.1
# e    1.0
# dtype: float64

50%: 中央値(median) 1/2分位数や50パーセンタイルなどとも呼ばれる。 median()メソッドで個別に算出可能。

print(df.median(numeric_only=True))
# a    1.5
# b    0.6
# e    1.0
# dtype: float64

25%, 75%: 1/4分位数、3/4分位数 第1四分位数、第3四分位数、または、25パーセンタイル、75パーセンタイルなどとも呼ばれる。

分位数 - Wikipedia

quantile()メソッドで個別に算出可能。算出するパーセンタイルの値を0から1の範囲でリスト指定します。

print(df.quantile(q=[0.25, 0.75], numeric_only=True))
#          a      b     e
# 0.25  1.00  0.325  0.75
# 0.75  2.25  0.875  1.00

quantile()を使うと最小値、最大値、中央値をまとめて算出することもできます。

print(df.quantile(q=[0, 0.25, 0.5, 0.75, 1], numeric_only=True))
#          a      b     e
# 0.00  1.00  0.100  0.00
# 0.25  1.00  0.325  0.75
# 0.50  1.50  0.600  1.00
# 0.75  2.25  0.875  1.00
# 1.00  3.00  1.100  1.00

describe()においても次に示す引数percentilesで算出するパーセンタイルを指定可能。

算出するパーセンタイルを指定

これまでの例のように、describe()ではデフォルトで最小値(0パーセンタイル)、中央値(50パーセンタイル)、最大値(100パーセンタイル)に加え、25パーセンタイル、75パーセンタイルが算出される。 最小値、中央値、最大値は常に算出されるが、それ以外は引数percentilesで指定できます。0から1までの範囲の値をリストで指定します。

print(df.describe(percentiles=[0.2, 0.4, 0.6, 0.8]))
#               a         b
# count  4.000000  4.000000
# mean   1.750000  0.600000
# std    0.957427  0.439697
# min    1.000000  0.100000
# 20%    1.000000  0.280000
# 40%    1.200000  0.480000
# 50%    1.500000  0.600000
# 60%    1.800000  0.720000
# 80%    2.400000  0.920000
# max    3.000000  1.100000

数値列に対して頻度などを算出

例えば、男性を0、女性を1で表したり地名を数値に割り当てているカテゴリデータなど、数値型でも平均や標準偏差ではなく最頻値やその頻度を確認したい場合があります。 そのような場合は、astype()メソッドで文字列に型変換(キャスト)します。すべての列の型を変えることも、個別に列を指定して変えることも可能。

print(df.astype('str').describe())
#         a    b  c  d     e
# count   4    4  4  4     4
# unique  3    4  3  4     2
# top     1  1.1  X  3  True
# freq    2    1  2  1     3

print(df.astype({'a': str}).describe(exclude='number'))
#         a  c  d     e
# count   4  4  4     4
# unique  3  3  4     2
# top     1  X  3  True
# freq    2  2  1     3

数字の文字列に対して平均や標準偏差などを算出

数字の文字列に対して平均や標準偏差などを算出したい場合も同様にastype()メソッドを使います。

print(df.astype({'d': int, 'e': int}).describe())
#               a         b         d     e
# count  4.000000  4.000000  4.000000  4.00
# mean   1.750000  0.600000  2.750000  0.75
# std    0.957427  0.439697  1.707825  0.50
# min    1.000000  0.100000  1.000000  0.00
# 25%    1.000000  0.325000  1.750000  0.75
# 50%    1.500000  0.600000  2.500000  1.00
# 75%    2.250000  0.875000  3.500000  1.00
# max    3.000000  1.100000  5.000000  1.00

pandas.Seriesのdescribe

pandas.Seriesにもdescribe()メソッドが用意されています。pandas.Seriesが返る。

s_int = df['a']
print(s_int)
# 0    1
# 1    2
# 2    1
# 3    3
# Name: a, dtype: int64

print(s_int.describe())
# count    4.000000
# mean     1.750000
# std      0.957427
# min      1.000000
# 25%      1.000000
# 50%      1.500000
# 75%      2.250000
# max      3.000000
# Name: a, dtype: float64

print(type(s_int.describe()))
# <class 'pandas.core.series.Series'>

引数include, excludeは無視され、型dtypeに応じた項目が算出される。astype()での型変換も可能。

s_str = df['d']
print(s_str.describe())
# count     4
# unique    4
# top       3
# freq      1
# Name: d, dtype: object

print(s_str.astype('int').describe())
# count    4.000000
# mean     2.750000
# std      1.707825
# min      1.000000
# 25%      1.750000
# 50%      2.500000
# 75%      3.500000
# max      5.000000
# Name: d, dtype: float64

日時(datetime64[ns]型)の場合

pandasには日時を表す型dtypeであるdatetime64[ns]があります。

datetime64[ns]型の列に対してはfirstとlastの項目が追加される。

df['dt'] = pd.to_datetime(['2018-01-01', '2018-03-15', '2018-02-20', '2018-03-15'])

print(df.dtypes)
# a              int64
# b            float64
# c             object
# d             object
# e               bool
# dt    datetime64[ns]
# dtype: object

print(df.describe(include='datetime'))
#                          dt
# count                     4
# unique                    3
# top     2018-03-15 00:00:00
# freq                      2
# first   2018-01-01 00:00:00
# last    2018-03-15 00:00:00

文字通り、firstは最初の日時、lastは最後の日時を示す。min(), max()で個別に算出可能。

print(df['dt'].min())
# 2018-01-01 00:00:00

print(df['dt'].max())
# 2018-03-15 00:00:00

行に対してdescribe()を適用

describe()には行・列を指定する引数axisはない。 .Tで転置してからdescribe()を呼べば元の行に対する結果が得られる。

print(df.T.describe())
#         0                    1                    2                    3
# count   6                    6                    6                    6
# unique  5                    6                    6                    6
# top     1  2018-03-15 00:00:00  2018-02-20 00:00:00  2018-03-15 00:00:00
# freq    2                    1                    1                    1

なお、pandasでは列ごとに型dtypeをもつので、基本的には列ごとに同種のデータが並んでいることを前提としています。 したがって本来は行ごとに要約統計量を求めることはあまりなく、行ごとに同種のデータが並んでいるのであれば転置しておいたほうがdescribe()に限らずもろもろの処理を行いやすい。

シェア

関連カテゴリー

Python pandas

pandasのオプション設定を確認・変更する方法 pandas.DataFrame, Seriesを順位付けするrank pandasのデータ型dtype一覧とastypeによる変換(キャスト) pandas.Seriesのmapメソッドで列の要素を置換 pandasで時系列データの曜日や月、四半期、年ごとの合計や平均を算出 pandasで最大値・最小値の行名・列名を取得するidxmax, idxmin pandas.DataFrameをGroupByでグルーピングし統計量を算出 pandasで時系列データのOHLC(四本値)を算出・ダウンサンプリング 『Python Data Science Handbook』(英語の無料オンライン版あり) pandas.DataFrame, Seriesを辞書に変換(to_dict) pandasで欠損値NaNが含まれているか判定、個数をカウント pandasの文字列から正規表現で抽出して新たな列を生成 pandasのピボットテーブルでカテゴリ毎の統計量などを算出 pandasでカテゴリ変数をダミー変数に変換(get_dummies)

Last Updated: 6/26/2019, 10:34:03 PM