Pandasは、データ分析を効率的に行うための機能を提供するライブラリです。データを行列として扱い、数値だけではなく、文字列のデータを扱えます。データ分析では表形式のデータ構造だと、データが扱いやすく、効率的に作業できます。
Pandasには、2種類のデータ構造が用意されています。一つはDataFrameで、もう一つはSeriesです。DataFrameは2次元の表で表されるデータを扱うもので、横は行、縦は列といいます。行と列にはそれぞれラベルをつけ、行のラベルはインデックス、列のラベルはカラムといいます。Seriesは一次元のデータを扱うもので、DataFrameの行、あるいは、列と考えることもできます。
Seriesは、一次元配列を扱うデータ構造です。Seriesでは、データを辞書型にしておくことで、辞書のキーでソートできます。辞書型というのは、{キー:バリュー}という組合せのデータの並びで、値を取り出すとき、キーを使います。データ(バリュー)と、それに関連付けたインデックス(キー)を指定することで、Seriesデータを生成します。
Seriesのデータ構造を持つデータを作り、確認してみましょう。
In
# Pandasをpdとしてimport
import pandas as pd
cars = {"Civic": 220, "Corolla": 270, "Note": 180}
print(pd.Series(cars))
Out
Civic 220
Corolla 270
Note 180
dtype: int64
この場合、CivicとかCorollaとかがインデックスで、数値がデータです。出力で、「dtype: int64」というのは、生成されたデータはint64型であるという意味です。dtypeは要素のデータ型を表し、整数であればint、実数であればfloatになります。int64は64ビットの整数で、-2^(63) ~ 2^(63) - 1 の範囲の整数を扱うことができます。
pd.Series(データ配列, index = インデックス配列)と記述すると、Seriesを生成できます。Seriesにインデックスを指定しないと、インデックスとして整数が"0"から順につけられます。
In
# Pandasをpdとしてimport
import pandas as pd
car_index = ["Civic","Corolla", "Note"]
data = [220, 270, 180]
# index と dataを含むSeriesに代入して下さい
series01 = pd.Series(data, index = car_index)
print(series01)
Out
Civic 220
Corolla 270
Note 180
dtype: int64
Seriesの要素を参照するには、番号を指定する方法とインデックス値を指定する方法とがあります。番号を指定する方法ではリストのスライス機能(series01[:2]とか)のように要素を指定し、任意の範囲を抽出することができます。インデックス値を指定する方法では、所望の要素のインデックス値をリストし直して参照できます。
In
# 番号を指定する方法
cars = {"Civic": 220, "Corolla": 270, "Note": 180}
series02 = pd.Series(cars)
print(series02[0:2]) # 番号の指定にはリストのスライス機能が使える
Out
Civic 200
Corolla 220
dtype: int64
In
# インデックス値を指定する方法
# 所望の要素のインデックス値を1つのリストにまとめる
print(series02[["Corolla", "Note"]])
Out
Corolla 220
Note 190
dtype: int64
Seriesのデータの値、あるいは、インデックスだけを抽出することができます。Sereis型の変数s1に対してs1.valuesでデータの値、s1.indexでインデックス値を参照できます。
In
# データやインデックスを抽出する
import pandas as pd
car = ["Civic", "Corolla", "Note", "CX-3", "Mirage"]
data = [11, 12, 13, 14, 15]
s1 = pd.Series(data, index = car)
s1_values = s1.values
s1_index = s1.index
print(s1_values)
print(s1_index)
Out
[11 12 13 14 15]
Index(['Civic', 'Corolla', 'Note', 'CX-3', 'Mirge'], dtype='object')
Series型の変数に要素を追加します。このとき、追加する要素もSeries型でないといけません。そのため、追加の要素をSeries型に変換しておきます。その上で、追加先の変数(Series型)にappend()することで要素を追加します。
In
# 要素の追加
subjects = {"English": 1, "Science": 2, "Society": 3}
sub1 = pd.Series(subjects)
print(sub1)
sub1 = sub1.append(pd.Series([4], index = ["mathematics"] ))
print(sub1)
Out
English 1
Science 2
Society 3
dtype: int64
English 1
Science 2
Society 3
Mathematics 4
dtype: int64
次に、Series型の変数からその要素を削除します。Series型の変数に対してdrop("インデックス")することで、指定のインデックスを持つ要素を削除できます。
In
# 要素の削除
sub2 = sub1.drop("Society")
print(sub2)
Out
English 1
Science 2
Mathematics 4
dtype: int64
Series型の変数に対して条件に合致する要素を取り出したり、要素を並べ直したりします。条件に合致した要素を取り出すには、bool型のシーケンスを指定して、Trueとなるものだけを抽出するようにします。要素を並べ直すにはインデックス値あるいはデータを用いてソートします。
In
# フィルタリング
car = ["Civic", "Corolla", "Note", "CX-3", "Mirage"]
data = [11, 12, 13, 14, 15]
s1 = pd.Series(data, index = car)
condition = [True, True, False, True, False]
print(s1[condition])
Out
Civic 11
Corolla 12
CX-3 14
dtype: int64
上の例ではbool型のシーケンスを作って、Trueで抽出する要素を指定しました。Sereis型の条件式を作成すると、bool型のシーケンスを取得できます。そうすると、Series型の変数s1に対して、s1[s1 >= 13]のように値が13以上の要素だけを取り出すことができます。また、s1[s1 >= 12][s1 <= 13]のように[ ]を複数、変数の後ろ側に添えると、複数の条件を付けくわえることができます。
In
print(s1[s1 >=13]) # 要素番号が13以上
print(s1[s1 >= 12][s1 <= 13]) # 要素番号が12以上、13以下
Out
Note 13
CX-3 14
Mirge 15
dtype: int64
Corolla 12
Note 13
dtype: int64
Series型のソートには、インデックス値による並べ替えと要素番号による並べ替えがあります。インデックス値による並べ替えでは、Series型の変数s1に対してs1.sort_index()として行います。要素番号による並べ替えでは、Series関数s1に対してs1.sort_values()として行います。defaltでは昇順にソートされ、引数にascending = Falseを指定すると降順にソートできます。
In
# ソート
import pandas as pd
car = ["Civic", "Corolla", "Note", "CX-3", "Mirage"]
data = [11, 12, 13, 14, 15]
s1 = pd.Series(data, index = car)
item1 = s1.sort_index() # インデックス値でソート
print(item1)
item2 = s1.sort_values() # 要素番号でソート
print(item2)
Out
CX-3 14
Civic 11
Corolla 12
Mirage 15
Note 13
dtype: int64
Civic 11
Corolla 12
Note 13
CX-3 14
Mirage 15
dtype: int64
DataFrameは、2次元の表形式(テーブル)のデータを表すための型です。Series型を複数重ねたような2次元のデータ構造を持っています。DataFrameを作るには以下に示すように、pd.DataFrame()に複数のSeries型を渡します。生成されたDataFrameには、行に"0"を起点とした番号が付与されます。
pd.DataFrame([Series, Series, ...])
In
# DataFrameを作る
import pandas as pd
car = ["Civic", "Corolla", "Note", "CX-3", "Mirage"]
data1 = [11, 12, 13, 14, 15]
s1 = pd.Series(data1, index = car)
data2 = [51, 52, 53, 54, 55]
s2 = pd.Series(data2, index = car)
df1 = pd.DataFrame([s1, s2])
print(df1)
Out
Civic Corolla Note CX-3 Mirage
0 11 12 13 14 15
1 51 52 53 54 55
辞書型データのバリューにリスト型を設定しておいて、それをpd.DataFrame()の引数に渡す、ということもできます。辞書型というのは、{キー1:バリュー1, キー2:バリュー2, ...}という形式のデータ型です。リスト型といのは["Python", "C++", "R"]というように、複数の要素を持つ形式のデータ型です。この場合、バリューに設定するリスト型の長さが等しくなっている必要があります。
In
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama"],
"year" : [2020, 2021, 2022, 2023],
"area" : [2194, 5158, 2416, 3798]}
df = pd.DataFrame(data)
print(df)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2021 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
DataFrame型データにはインデックスとカラムを設定することができます。インデックスは行の名前であり、カラムは列の名前です。インデックスを指定しないと、DataFrameのインデックスは"0"から昇順に数字が割り当てられます。カラムは、DataFrameの元データであるSeriesのインデックスや辞書型のキーになります。
DataFrame型の変数df2があったとして、そのインデックスを設定するには、df2.indexに、行数と同じ数のリスト型データを代入します。カラムを設定するには、df2.columnsに、列数と同じ数のリスト型データを代入します。
df2.index = ["row1", "row2", ...]
df2.columns = ["column1", "column2", ...]
In
# インデックスとカラムの設定
import pandas as pd
data1 = [11, 12, 13, 14, 15]
s1 = pd.Series(data1)
data2 = [51, 52, 53, 54, 55]
s2 = pd.Series(data2)
df2 = pd.DataFrame([s1, s2])
print(df2)
# インデックスが1から始まるように設定する
df2.index = [1, 2]
# カラム(列名)を設定する
df2.columns = ["Civic", "Corolla", "Note", "CX-3", "Mirage"]
print(df2)
Out
0 1 2 3 4
0 11 12 13 14 15
1 51 52 53 54 55
Civic Corolla Note CX-3 Mirage
1 11 12 13 14 15
2 51 52 53 54 55
既存のDataFrameにデータを追加するには、DataFrame型の変数df2に対してdf2.append("Series型のデータ", ignore_index = True)を適用します。append()に渡すSeries型のデータのインデックス値がdf2のカラムに割り当てられ、元のDataFrameに対して新しい行が追加されます。
In
# 行の追加
import pandas as pd
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama"],
"year" : [2020, 2021, 2022, 2023],
"area" : [2194, 5158, 2416, 3798]}
df = pd.DataFrame(data)
print(df)
s3 = pd.Series(["Tochigi", 2024, 6408],
index = ["city", "year", "area"])
df = df.append(s3, ignore_index = True)
print(df)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2021 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
city year area
0 Tokyo 2020 2194
1 Chiba 2021 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
4 Tochigi 2024 6408
DataFrame型の変数にappend("Series型のデータ", ignore_index = True)を適用して、Series型のデータを渡します。そのインデックス値が、DataFrameのカラムに対応する形で行が加わります。このとき、DataFrameのカラムと、追加するSeries型のデータのインデックス値が一致しないと、DataFrameには新しいカラムが追加されますが、値がない要素はNaN (Not a Number)になります。
In
# 要素が存在しないときの挙動
import pandas as pd
car = ["Civic", "Corolla", "Note", "CX-3", "Mirage"]
data1 = [11, 12, 13, 14, 15]
s1 = pd.Series(data1, index = car)
data2 = [51, 52, 53, 54, 55]
s2 = pd.Series(data2, index = car)
# df2にs3を追加し、df2に再代入する
data3 = [101, 102, 103, 104, 105, 106]
car.append("Legacy")
s3 = pd.Series(data3, index = car)
df3 = pd.DataFrame([s1, s2])
print(df3)
df3 = df3.append(s3, ignore_index = True)
print(df3)
Out
Civic Corolla Note CX-3 Mirage
0 11 12 13 14 15
1 51 52 53 54 55
Civic Corolla Note CX-3 Mirage Legacy
0 11 12 13 14 15 NaN
1 51 52 53 54 55 NaN
2 101 102 103 104 105 106.0
列(カラム)の追加も同様に行えます。列の追加は、行列データに属性を追加するような場合に必要になります。既存のDataFrameに列を追加するには、DataFrame型の変数df4に対して、
df4["新しいカラム名"] = Seriesあるいはリスト
というように、Seriesあるいはリストを代入します。
Seriesを代入したら、Seriesのインデックス値がdf4のインデックス値に対応します。
In
# 列(カラム)の追加:Seriesの代入
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama"],
"year" : [2020, 2021, 2022, 2023],
"area" : [2194, 5158, 2416, 3798]}
df4 = pd.DataFrame(data)
print(df4)
# df4に列を追加する
new_column = pd.Series([1396, 628, 906, 734], index = [0, 1, 2, 3])
df4["population"] = new_column
print(df4)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2021 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
city year area population
0 Tokyo 2020 2194 1396
1 Chiba 2021 5158 628
2 Kanagawa 2022 2416 906
3 Saitama 2023 3798 734
リストを代入したら、行の一番目から順に要素が割り当てられます。
In
# 列(カラム)の追加:リストの代入
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama"],
"year" : [2020, 2021, 2022, 2023],
"area" : [2194, 5158, 2416, 3798]}
df4 = pd.DataFrame(data)
print(df4)
# df4に列を追加する
df4["population"] = [1396, 628, 906, 734]
print(df4)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2021 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
city year area population
0 Tokyo 2020 2194 1396
1 Chiba 2021 5158 628
2 Kanagawa 2022 2416 906
3 Saitama 2023 3798 734
DataFrameの行と列を指定すると、そのデータを取り出すことができます。これを、データの参照といいます。参照の方法として、名前による参照と番号による参照があります。
・名前による参照:loc
・番号による参照:iloc
以下、それぞれ順に説明していきます。
名前による参照ではDataFrameのインデックスもしくはカラムの名前を使って参照します。DataFrame型の変数dfがあったとして、
df.loc["インデックスのリスト", "カラムのリスト"]
のように行と列を指定することで、指定範囲のデータを抽出します。
In
# 名前による参照
import pandas as pd
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama", "Tochigi"],
"year" : [2020, 2021, 2022, 2023, 2024],
"area" : [2194, 5158, 2416, 3798, 6408]}
df = pd.DataFrame(data)
print(df)
df1 = df.loc[[1, 2], ["year", "area"]]
print(df1)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2021 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
4 Tochigi 2024 6408
year area
1 2021 5158
2 2022 2416
range()を使えば、範囲を指定できます。DataFrameの2行目から4行目(インデックス値:1-3)までの3行を抽出するなら、以下のようにします。
In
# 名前による参照
df2 = df.loc[range(1,4)] # <- 指定範囲に注意
print(df2)
Out
city year area
1 Chiba 2021 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
番号による参照ではDataFrameの行番号・列番号を指定してデータを参照します。DataFrame型の変数dfがあったとして、
df.iloc["行番号のリスト", "列番号のリスト"]
のように行と列を指定することで、指定範囲のデータを抽出します。名前による参照では「loc」を使いましたが、番号による参照では「iloc」を使います。また、番号の指定は行・列ともに「0」から始まる点に注意します。リストを渡す代わりに、スライス機能を使うこともできます。
In
# 番号による参照
import pandas as pd
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama", "Tochigi"],
"year" : [2020, 2021, 2022, 2023, 2024],
"area" : [2194, 5158, 2416, 3798, 6408]}
df = pd.DataFrame(data)
print(df)
df1 = df.iloc[[1, 2], [0, 2]] # 行番号のリスト , 列番号のリスト
print(df1)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2021 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
4 Tochigi 2024 6408
city area
1 Chiba 5158
2 Kanagawa 2416
行あるいは列を削除するには、DataFrameのインデックスもしくはカラムを指定することによって、行もしくは列を削除します。DataFrame型の変数dfがあったとして、
df.drop("インデックス")
df.drop("カラム", axis = 1)
のように行もしくは列を指定することで、指定範囲のデータを削除します。インデックスもしくはカラムをリストで渡すと、まとめて削除できます。列を削除するとき、第2引数に axis = 1 を設定する必要があります。
In
# 行・列の削除
import pandas as pd
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama", "Tochigi"],
"year" : [2020, 2021, 2022, 2023, 2024],
"area" : [2194, 5158, 2416, 3798, 6408]}
df = pd.DataFrame(data)
print(df)
# drop()でdfの0, 1行目を削除
df1 = df.drop(range(0, 2))
print(df1)
df2 = df.drop("year", axis = 1)
print(df2)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2021 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
4 Tochigi 2024 6408
city year area
2 Kanagawa 2022 2416
3 Saitama 2023 3798
4 Tochigi 2024 6408
city area
0 Tokyo 2194
1 Chiba 5158
2 Kanagawa 2416
3 Saitama 3798
4 Tochigi 6408
DataFrameの列の値を昇順に並べるには、sort_values()を使います。DataFrame型の変数dfがあったとして、
df.sort_values(by = "カラム(のリスト)", ascending = True)
のように、ソートするカラムを指定します。ascending = Trueが昇順で、ascending = Falseが降順です。defaultは昇順です。カラムのリストを指定したら、リストの順番の若いカラムから優先的にソートされます。
In
# ソート
import pandas as pd
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama", "Tochigi"],
"year" : [2020, 2022, 2022, 2023, 2024],
"area" : [2194, 5158, 2416, 3798, 6408]}
df = pd.DataFrame(data)
print(df)
# 引数にカラム(year)を指定し、昇順ソート
df1 = df.sort_values(by = "area", ascending = True)
print(df1)
# 引数にカラムのリスト["area", "year"]を指定し、昇順ソート
df2 = df.sort_values(by = ["year", "area"], ascending = True)
print(df2)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2022 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
4 Tochigi 2024 6408
city year area
0 Tokyo 2020 2194
2 Kanagawa 2022 2416
3 Saitama 2023 3798
1 Chiba 2022 5158
4 Tochigi 2024 6408
city year area
0 Tokyo 2020 2194
2 Kanagawa 2022 2416
1 Chiba 2022 5158
3 Saitama 2023 3798
4 Tochigi 2024 6408
フィルタリングはbool型のシーケンスを指定することで、TrueのデータだけをDataFrameから抽出します。シーケンスというのは、要素がある順序で並んでいて、その順序でその要素を指定できるオブジェクトのことでした。">"や"<=", "=="といった演算子を使って、値の大小を判定できます。
In
# フィルタリング:偶数行のデータを抽出
import pandas as pd
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama", "Tochigi"],
"year" : [2020, 2022, 2022, 2023, 2024],
"area" : [2194, 5158, 2416, 3798, 6408]}
df = pd.DataFrame(data)
print(df)
print(df.index % 2 == 0)
df1 = df[df.index % 2 == 0]
print(df1)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2022 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
4 Tochigi 2024 6408
[ True False True False True]
city year area
0 Tokyo 2020 2194
2 Kanagawa 2022 2416
4 Tochigi 2024 6408
DataFrameを用いた条件式からbool型のシーケンスを抽出できます。この条件式を用いることで、フィルタリングできます。例えば、DataFrame型の変数dfがあったとして、
df.loc[ df[ "カラム(列)" ]を含む条件式 ]
とやると、この条件に一致する要素の行を持つDataFrameを作ることができます。
In
# フィルタリング:条件に合致したデータを抽出
import pandas as pd
data = {"city" : ["Tokyo", "Chiba", "Kanagawa", "Saitama", "Tochigi"],
"year" : [2020, 2022, 2022, 2023, 2024],
"area" : [2194, 5158, 2416, 3798, 6408]}
df = pd.DataFrame(data)
print(df)
df1 = df.loc[df["year"] >= 2022]
print(df1)
df2 = df1.loc[df1["area"] <= 4000]
print(df2)
Out
city year area
0 Tokyo 2020 2194
1 Chiba 2022 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
4 Tochigi 2024 6408
city year area
1 Chiba 2022 5158
2 Kanagawa 2022 2416
3 Saitama 2023 3798
4 Tochigi 2024 6408
city year area
2 Kanagawa 2022 2416
3 Saitama 2023 3798