pandasで特定の条件を満たす要素数をカウント(全体、行・列ごと)

Modified: | Tags: Python, pandas

pandasでDataFrame, Seriesの特定の条件を満たす要素の数を行・列ごとおよび全体でカウントする方法を説明する。

最後に紹介するように、DataFrameSeriescount()メソッドは欠損値でない要素の数をカウントする。

条件を満たす行を抽出する方法、各列ごとにユニークな要素の数をカウントする方法については以下の記事を参照。

本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。例として以下のデータを使用する。

import pandas as pd

print(pd.__version__)
# 2.1.4

df = pd.read_csv('data/src/sample_pandas_normal.csv')
print(df)
#       name  age state  point
# 0    Alice   24    NY     64
# 1      Bob   42    CA     92
# 2  Charlie   18    CA     70
# 3     Dave   68    TX     70
# 4    Ellen   24    CA     88
# 5    Frank   30    NY     57

特定の条件を満たす要素数をカウントする流れ

特定の条件を満たす要素数をカウントする流れは以下の通り。

  1. 各要素を判定しbool型(True, False)のDataFrame, Seriesを取得
    • 比較演算子や文字列アクセサなどを利用
  2. sum()メソッドでカウント
    • DataFrame
      • 列ごとにカウント: sum()
      • 行ごとにカウント: sum(axis=1)
      • 全体でカウント: sum().sum()またはvalues.sum()
    • Series
      • 全体でカウント: sum()

DataFrameの例

DataFrame, Seriesに対して比較演算子を適用すると、各要素ごとに判定され、同じサイズのbool型(True, False)のDataFrame, Seriesが取得できる。

右辺の括弧()は省略可能。

df_bool = (df == 'CA')
print(df_bool)
#     name    age  state  point
# 0  False  False  False  False
# 1  False  False   True  False
# 2  False  False   True  False
# 3  False  False  False  False
# 4  False  False   True  False
# 5  False  False  False  False

PythonにおいてTrue1False0とみなされるため、sum()メソッドで合計を算出することで条件を満たす要素の数が得られる。デフォルトは列ごと、引数axis=1とすると行ごとのカウントとなる。

print(df_bool.sum())
# name     0
# age      0
# state    3
# point    0
# dtype: int64

print(df_bool.sum(axis=1))
# 0    0
# 1    1
# 2    1
# 3    0
# 4    1
# 5    0
# dtype: int64

DataFramesum()Seriesを返す。さらにSeriessum()を呼ぶことで、総数を得られる。

print(df_bool.sum().sum())
# 3

また、DataFramevalues属性でNumPy配列ndarrayに変換できる。

ndarraysum()メソッドはデフォルトで全体の合計を算出するため、values属性(ndarray)からsum()を呼ぶと条件を満たす要素の総数(全体の個数)が取得できる。

print(df_bool.values)
# [[False False False False]
#  [False False  True False]
#  [False False  True False]
#  [False False False False]
#  [False False  True False]
#  [False False False False]]

print(type(df_bool.values))
# <class 'numpy.ndarray'>

print(df_bool.values.sum())
# 3

続けて書いてもよい。

print((df == 'CA').sum())
# name     0
# age      0
# state    3
# point    0
# dtype: int64

print((df == 'CA').sum(axis=1))
# 0    0
# 1    1
# 2    1
# 3    0
# 4    1
# 5    0
# dtype: int64

print((df == 'CA').sum().sum())
# 3

print((df == 'CA').values.sum())
# 3

なお、数値と文字列の列が混在するDataFrameに対して数値との比較演算を行うと、文字列と数値が比較されてしまいエラーとなるので注意。詳細は「数値に対する条件」の節で述べる。

Seriesの例

以下のSeriesを例とする。

s = df['age']
print(s)
# 0    24
# 1    42
# 2    18
# 3    68
# 4    24
# 5    30
# Name: age, dtype: int64

やり方はDataFrameと同じ。Seriesは一次元データなので、sum()メソッドは総数を返す。

s_bool = (s < 25)
print(s_bool)
# 0     True
# 1    False
# 2     True
# 3    False
# 4     True
# 5    False
# Name: age, dtype: bool

print(s_bool.sum())
# 3

print((s < 25).sum())
# 3

DataFrameの任意の行・列に対して条件を満たす要素をカウントする場合は、[]loc[], iloc[]などで行・列を指定して同様の処理を行えばよい。

複数条件の論理積(かつ)、論理和(または)、否定(でない)

複数条件を組み合わせるには、各条件式を括弧()で囲んだ上で、&演算子(論理積、AND、かつ)や|演算子(論理和、OR、または)で接続する。~演算子(否定、NOT、でない)も使用可能。

print((df == 'CA') | (df == 70))
#     name    age  state  point
# 0  False  False  False  False
# 1  False  False   True  False
# 2  False  False   True   True
# 3  False  False  False   True
# 4  False  False   True  False
# 5  False  False  False  False
print(~(df == 'CA'))
#    name   age  state  point
# 0  True  True   True   True
# 1  True  True  False   True
# 2  True  True  False   True
# 3  True  True   True   True
# 4  True  True  False   True
# 5  True  True   True   True
print((df['state'] == 'CA') & (df['age'] < 30))
# 0    False
# 1    False
# 2     True
# 3    False
# 4     True
# 5    False
# dtype: bool

&, |ではなくand, orを使ったり、括弧を省略したりするとエラーになるので注意。

例は省略するが、bool型(True, False)のDataFrameSeriesが取得できれば、上述のように、sum()メソッドなどで条件を満たす要素をカウントできる。

数値に対する条件を指定してカウント

これまでの例でも登場しているが、数値に対しては比較演算子<, <=, >, >=, ==, !=などが使用できる。

文字列の列を含むDataFrameに対して<>などで数値と比較するとエラーになるので注意。数値列のみ抽出するにはselect_dtypes()を使う。

# print(df < 65)
# TypeError: '<' not supported between instances of 'str' and 'int'

df_num = df.select_dtypes('number')
print(df_num)
#    age  point
# 0   24     64
# 1   42     92
# 2   18     70
# 3   68     70
# 4   24     88
# 5   30     57

print((df_num < 65).sum())
# age      5
# point    2
# dtype: int64

print(((df_num > 35) & (df_num < 65)).sum())
# age      1
# point    2
# dtype: int64

文字列に対する条件を指定してカウント

文字列に対しては==!=のほかSeriesの文字列アクセサstrによって以下のようなメソッドが使用可能。

  • str.contains(): 特定の文字列を含む
  • str.endswith(): 特定の文字列で終わる
  • str.startswith(): 特定の文字列で始まる
  • str.match(): 正規表現のパターンに一致する

文字列アクセサはSeriesのものでDataFrameでは使えないので注意。

df_str = df[['name', 'state']]
print(df_str)
#       name state
# 0    Alice    NY
# 1      Bob    CA
# 2  Charlie    CA
# 3     Dave    TX
# 4    Ellen    CA
# 5    Frank    NY

print((df_str == 'NY').sum())
# name     0
# state    2
# dtype: int64

print(df_str['name'].str.endswith('e'))
# 0     True
# 1    False
# 2     True
# 3     True
# 4    False
# 5    False
# Name: name, dtype: bool

print(df_str['name'].str.endswith('e').sum())
# 3

文字列アクセサを利用して条件を満たす行を抽出する方法については以下の記事を参照。

欠損値NaNの数、NaNでない要素の数をカウント

欠損値NaNを含む例としてタイタニックの生存者のデータを使用する。

df_titanic = pd.read_csv('data/src/titanic_train.csv')
print(df_titanic.head())
#    PassengerId  Survived  Pclass  \
# 0            1         0       3   
# 1            2         1       1   
# 2            3         1       3   
# 3            4         1       1   
# 4            5         0       3   
# 
#                                                 Name     Sex   Age  SibSp  \
# 0                            Braund, Mr. Owen Harris    male  22.0      1   
# 1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  38.0      1   
# 2                             Heikkinen, Miss. Laina  female  26.0      0   
# 3       Futrelle, Mrs. Jacques Heath (Lily May Peel)  female  35.0      1   
# 4                           Allen, Mr. William Henry    male  35.0      0   
# 
#    Parch            Ticket     Fare Cabin Embarked  
# 0      0         A/5 21171   7.2500   NaN        S  
# 1      0          PC 17599  71.2833   C85        C  
# 2      0  STON/O2. 3101282   7.9250   NaN        S  
# 3      0            113803  53.1000  C123        S  
# 4      0            373450   8.0500   NaN        S  

欠損値NaNの削除や置換、判定については以下の記事を参照。

欠損値NaNの数をカウント

欠損値NaNの数をカウントするには、各要素がNaNかどうかを判定するisnull()メソッドを使う。数をカウントするには、これまでの例と同様、さらにsum()を適用すればよい。

print(df_titanic.isnull().head())
#    PassengerId  Survived  Pclass   Name    Sex    Age  SibSp  Parch  Ticket  \
# 0        False     False   False  False  False  False  False  False   False   
# 1        False     False   False  False  False  False  False  False   False   
# 2        False     False   False  False  False  False  False  False   False   
# 3        False     False   False  False  False  False  False  False   False   
# 4        False     False   False  False  False  False  False  False   False   
# 
#     Fare  Cabin  Embarked  
# 0  False   True     False  
# 1  False  False     False  
# 2  False   True     False  
# 3  False  False     False  
# 4  False   True     False  

print(df_titanic.isnull().sum())
# PassengerId      0
# Survived         0
# Pclass           0
# Name             0
# Sex              0
# Age            177
# SibSp            0
# Parch            0
# Ticket           0
# Fare             0
# Cabin          687
# Embarked         2
# dtype: int64

print(df_titanic.isnull().sum(axis=1).head())
# 0    1
# 1    0
# 2    1
# 3    0
# 4    1
# dtype: int64

print(df_titanic.isnull().values.sum())
# 866

欠損値NaNでない要素の数をカウント: count()

欠損値Nanではない要素の数をカウントするにはcount()メソッドを使う。sum()と同様、引数を省略すると列、引数axis=1とすると行に対する処理となる。

print(df_titanic.count())
# PassengerId    891
# Survived       891
# Pclass         891
# Name           891
# Sex            891
# Age            714
# SibSp          891
# Parch          891
# Ticket         891
# Fare           891
# Cabin          204
# Embarked       889
# dtype: int64

print(df_titanic.count(axis=1).head())
# 0    11
# 1    12
# 2    11
# 3    12
# 4    11
# dtype: int64

print(df_titanic.count().sum())
# 9826

print(df_titanic['Age'].count())
# 714

欠損値Nanでない要素の数を確認するだけならinfo()メソッドで表示できる。

df_titanic.info()
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 891 entries, 0 to 890
# Data columns (total 12 columns):
#  #   Column       Non-Null Count  Dtype  
# ---  ------       --------------  -----  
#  0   PassengerId  891 non-null    int64  
#  1   Survived     891 non-null    int64  
#  2   Pclass       891 non-null    int64  
#  3   Name         891 non-null    object 
#  4   Sex          891 non-null    object 
#  5   Age          714 non-null    float64
#  6   SibSp        891 non-null    int64  
#  7   Parch        891 non-null    int64  
#  8   Ticket       891 non-null    object 
#  9   Fare         891 non-null    float64
#  10  Cabin        204 non-null    object 
#  11  Embarked     889 non-null    object 
# dtypes: float64(2), int64(5), object(5)
# memory usage: 83.7+ KB

関連カテゴリー

関連記事