Pandasとは
PandasはPythonの拡張モジュールで、データ解析を支援する機能を提供してくれます。
AIを作るにも事前のデータ解析が重要ですが、Pandas(+Jupyter Notebook)があればとても便利に解析できます。
また、人工知能フレームワークの入力に使われていたりますので、人工知能を勉強する上で使い方を知っておくことは重要です。
ここでは、Pandasでできることをまとめています。
Pandasのインストール
pipを使えば、以下のコマンドでPandasを簡単にインストールすることが出来ます。
# pip install pandas
Pandasのインポート
以下の「おまじない」でPandasの使用が可能になります。省略名は「pd」にすることが多いようです。
import pandas as pd
以降のコードは、上記の「おまじない」が実行済みであることを前提に記述します。
また、NumPyもよく使いますので、NumPyも省略名「np」としてインポートされている前提で記述します。
Series型とDataFrame型
Pandasを使用してデータ解析を行っていくのですが、Pandasでは解析対象のデータを格納するための型が存在します。それが、Series型とDataFrame型です。
Series型
NumPy配列が「Pythonのlist型のようなもの」とするなら、Series型は「Pythonの辞書型(dict型)のようなもの」です。
辞書型のキーのようにデータにラベルを付けれますし、他にもいろいろな処理を行うことができます。
また、次に紹介するDataFrame型での1列分のデータ、または1レコード(1行)分のデータに相当します。
Series型の作成
主にlist型と辞書型から、Series型を作成できます。
辞書型(dict型)から作成
Pandasの*Series()*で、辞書型(dict型)からSeries型を作成することができます。
辞書型のキーがSeries型のラベルに、辞書型の要素がSeries型のデータになります。
Science = {"akiyama": 100, "satou": 75, "tanaka": 120}
# SR = akiyama 100
# satou 75
# tanaka 120
# dtype: int64
SR = pd.Series(Science)
NumPy配列とlist型から作成
Pandasの*Series()*で、list型またはNumPy配列からSeries型を作成することができます。
list型で作成した場合、ラベルは「0」からの連番が振られますが、別途ラベルを指定することもできます。
record = [100, 75, 120]
record_np = np.array(record)
labels = ["akiyama", "satou", "tanaka"]
# ラベルは「0」からの連番
# SR = 0 100
# 1 75
# 2 120
# dtype: int64
SR = pd.Series(record)
SR = pd.Series(record_np)
# 「index」でラベルを指定
# SR = akiyama 100
# satou 75
# tanaka 120
# dtype: int64
SR = pd.Series(record, index=labels)
SR = pd.Series(record_np, index=labels)
Series型の操作
Series型にすると、様々な操作を行うことができます。
ラベルのみ表示、データのみ表示
Series型はindexでラベルのみ表示、valuesでデータのみ表示させることができます。
Science = {"akiyama": 100, "satou": 75, "tanaka": 120}
# SR = akiyama 100
# satou 75
# tanaka 120
# dtype: int64
SR = pd.Series(Science)
# SR.index = Index(['akiyama', 'satou', 'tanaka'], dtype='object')
SR.index
# SR.valuesはNumPy配列
# SR.values = [100 75 120]
SR.values
Series型とラベルに名前を付ける
Series型はnameで名前を付けられます。また、index.nameでラベルにも名前を付けられます。
Science = {"akiyama": 100, "satou": 75, "tanaka": 120}
SR = pd.Series(Science)
# SR = Students
# akiyama 100
# satou 75
# tanaka 120
# Name: Science, dtype: int64
SR.name = 'Science'
SR.index.name = 'Students'
新しいラベルを追加・ラベルを変更
Series型に新しいラベルを追加したい場合は、以下のようにすることで追加ですます。
Science = {"akiyama": 100, "satou": 75, "tanaka": 120}
# SR = akiyama 100
# satou 75
# tanaka 120
# dtype: int64
SR = pd.Series(Science)
# ラベルのlist型を使ってSeries型を作り直すと、新しいラベルが追加されたSeries型を取得できる
# この際、元のSeries型にないラベルは引き継がれない
# SR_new = akiyama 100.0
# satou 75.0
# nico NaN
# mochidan NaN
# dtype: float64
labels = ["akiyama", "satou", "nico", "mochidan"]
SR_new = pd.Series(SR, index=labels)
Series型のデータにアクセス
Series型は、添字やラベル名でデータにアクセスすることができます。
Science = {"akiyama": 100, "satou": 75, "tanaka": 120}
# SR = akiyama 100
# satou 75
# tanaka 120
# dtype: int64
SR = pd.Series(Science)
# tmp = 75
tmp = SR[1]
tmp = SR["satou"]
# スライスやlist型を使った指定も可能
# この場合、Series型が返却される
# tmp2 = akiyama 100
# satou 75
# dtype: int64
tmp2 = SR[0:2]
tmp2 = SR[["akiyama", "satou"]]
データにnull(欠損値)があるか判定
Pandasのisnull()、または*notnull()*でデータにnullがあるか判定できます。
Science = {"akiyama": 100, "satou": 75, "tanaka": 120}
SR = pd.Series(Science)
SR["satou"] = np.nan
# SR["satou"]が欠損値(null)
# 欠損値があると、データ型がfloat64に変わる
# SR = akiyama 100.0
# satou NaN
# tanaka 120.0
# dtype: float64
SR
# akiyama False
# satou True
# tanaka False
# dtype: bool
pd.isnull(SR)
# akiyama True
# satou False
# tanaka True
# dtype: bool
pd.notnull(SR)
条件を満たすデータを表示・変更
条件を満たすデータの判定、および条件を満たすデータを表示・変更が行えます。
Science = {"akiyama": 100, "satou": 75, "tanaka": 120}
# SR = akiyama 100
# satou 75
# tanaka 120
# dtype: int64
SR = pd.Series(Science)
# 80を超えるデータの判定
# 判定結果はSeries型として取得
# is_Excellent = akiyama True
# satou False
# tanaka True
# dtype: bool
is_Excellent = SR > 80
# 80を超えるデータのみ、Series型として取得
# Excellent = akiyama 100
# tanaka 120
# dtype: int64
Excellent = SR[SR > 80]
Excellent = SR[is_Excellent]
# 値を代入することで、条件を満たすデータを更新
# SR = akiyama 80
# satou 75
# tanaka 80
# dtype: int64
SR[SR > 80] = 80
指定したデータを削除
Series型の*drop()*を使用することで、指定したデータが削除されたSeries型を取得することができます。
Science = {"akiyama": 100, "satou": 75, "tanaka": 120}
# SR = akiyama 100
# satou 75
# tanaka 120
# dtype: int64
SR = pd.Series(Science)
# 削除する行のラベル名を指定
# SR_new = akiyama 100
# tanaka 120
# dtype: int64
SR_new = SR.drop("satou")
データをソート
Series型の*sort_index()*でラベルをキーに、*sort_values()*でデータをキーに並び替えを行うことができます。
Science = {"satou": 100, "akiyama": 75, "tanaka": 120}
# SR = satou 100
# akiyama 75
# tanaka 120
# dtype: int64
SR = pd.Series(Science)
# ラベルをキーに昇順でソート
# SR_index = akiyama 75
# satou 100
# tanaka 120
# dtype: int64
SR_index = SR.sort_index()
# 引数の「inplace」を「True」にすると、Series型そのものが更新される
SR.sort_index(inplace = True)
# 引数の「ascending」を「False」にすると、降順ソートとなる
SR.sort_index(inplace = True, ascending=False)
# データをキーに昇順でソート
# SR_values = akiyama 75
# satou 100
# tanaka 120
# dtype: int64
SR_values = SR.sort_values()
# 引数の「inplace」を「True」にすると、Series型そのものが更新される
SR.sort_values(inplace = True)
# 引数の「ascending」を「False」にすると、降順ソートとなる
SR.sort_values(inplace = True, ascending=False)
DataFrame型
DataFrame型は「表のようなもの」です。
解析対象となるデータは、csv形式、Excel形式やHTML上のデータだったりしますが、これらを読み込んで表として操作する機能を提供してくれます。
DataFrame型の作成
様々な形式のデータをDataFrame型として読み込むことができます。
csvファイルから作成
Pandasのread_csv()、または*read_table()*で、csvファイルからDataFrame型を作成することができます。
例として、以下のようなcsvファイルが存在する。
No,Name,Score
Students,Science,Math
akiyama,100,100
satou,75,99
tanaka,120,150
suzuki,50,50
mochidan,0,10
*read_csv()*を使用する場合は、以下のようにしてDataFrame型を作成できます。
# 引数は読み込み先のパスで、カレントディレクトリからの相対パスで指定
DF = pd.read_csv('test.csv')
# 「header」にNoneを指定すると、1行目からデータとして読み込む
DF = pd.read_csv('test.csv', header=None)
*read_table()*を使用する場合は、セパレータの指定が可能です。
以下のようにしてDataFrame型を作成できます。
# 引数は読み込み先のパスで、カレントディレクトリからの相対パスで指定
# 「sep」にセパレータを指定
DF = pd.read_table('test.csv', sep=',')
# 「header」にNoneを指定すると、1行目からデータとして読み込む
DF = pd.read_table('test.csv', , sep=',', header=None)
これら場合、DFは以下のようなDataFrame型となります。
※「header=None」無しで作成した場合のDataFrame型です。1行目は列名として読まれています。
Students | Science | Math | |
---|---|---|---|
0 | akiyama | 100 | 100 |
1 | satou | 75 | 99 |
2 | tanaka | 120 | 150 |
3 | suzuki | 50 | 50 |
4 | mochidan | 0 | 10 |
クリップボードから作成
Pandasの*read_clipboard()*で、クリップボードからDataFrame型を作成することができます。
例として、以下のような表が存在する。
Students | Science | Math | |
---|---|---|---|
0 | akiyama | 100 | 100 |
1 | satou | 75 | 99 |
2 | tanaka | 120 | 150 |
3 | suzuki | 50 | 50 |
4 | mochidan | 0 | 10 |
上記の表をコピーして、クリップボードに保存したとします。
その後は以下のようにして、DataFrame型を作成できます。
DF = pd.read_clipboard()
# 「header」にNoneを指定すると、1行目からデータとして読み込む
DF = pd.read_clipboard(header=None)
Excelファイルから作成
Pandasの*read_excel()*で、ExcelファイルからDataFrame型を作成することができます。
ただし、結合されたセルが存在した場合、セルの結合が解除され、値であれば「NaN」、列名であれば「Unnamed: x」となってしまうことに注意してください。
# 第一引数は読み込み先のパスで、カレントディレクトリからの相対パスで指定
# sheet_nameに読み込むシートの名前を指定
DF = pd.read_excel('test.xlsx', sheet_name='Sheet1')
# 「header」にNoneを指定すると、Excelファイルの1行目からデータとして読み込む
DF = pd.read_excel('test.xlsx', sheet_name='Sheet1', header=None)
辞書型(dict型)から作成
辞書型(dict型)からも、DataFrame型を作成することができます。
HTTPリクエスト等でJSONのデータが返却される場合、そのJSONをうまく辞書型にできればDataFrame型としてデータ操作することができます。
import pandas as pd
import json
# 例えば、こんなJSONがあった場合
json_obj = """
{
"result": [{"Students": "akiyama", "Science": 100, "Math": 100},
{"Students": "satou" , "Science": 75, "Math": 99},
{"Students": "tanaka" , "Science": 120, "Math": 150}]
}
"""
# JSONオブジェクトを作成
data = json.loads(json_obj)
# この場合、data["result"]は辞書型のリスト
# data["result"] = [{'Students': 'akiyama', 'Science': 100, 'Math': 100},
# {'Students': 'satou' , 'Science': 75, 'Math': 99},
# {'Students': 'tanaka' , 'Science': 120, 'Math': 150}]
data["result"]
# PandasのDataFrame()の引数に辞書型のリストを渡せば、DataFrame型にできる
# 1辞書型、1行のDataFrame型になる
DF = pd.DataFrame(data["result"])
この場合、DFは以下のようなDataFrame型となります。
Students | Science | Math | |
---|---|---|---|
0 | akiyama | 100 | 100 |
1 | satou | 75 | 99 |
2 | tanaka | 120 | 150 |
NumPy配列とlist型から作成
NumPy配列とlist型からも、DataFrame型を作成することができます。
# data_np = [['akiyama' 100 100],
# ['satou' 75 99]]
data = [["akiyama", 100, 100], ["satou", 75, 99]]
data_np = np.array(data)
# 「columns」に列名を指定(指定なしの場合は「0」からの連番)
DF = pd.DataFrame(data, columns = ['No', 'Name', 'Score'])
DF = pd.DataFrame(data_np, columns = ['No', 'Name', 'Score'])
この場合、DFは以下のようなDataFrame型となります。
Students | Science | Math | |
---|---|---|---|
0 | akiyama | 100 | 100 |
1 | satou | 75 | 99 |
DataFrame型の保存
DataFrame型をファイルとして保存することができます。
csv形式で保存
DataFrame型の*to_csv()*を使用することで、DataFrame型をcsv形式で保存することができます。
# なんらかの方法でDataFrame型を作成し、いろいろ編集を行ったとします
DF = pd.read_csv('test.csv')
# 第一引数は保存先のパスで、カレントディレクトリからの相対パスで指定
# セパレータのデフォルトは「,」
DF.to_csv('test_2.csv')
# 「sep」でセパレータを指定することもできます
DF.to_csv('test_3.csv', sep='_')
# インデックスとヘッダの有無を選択可能
DF.to_csv("test_4.csv", header=False, index=False)
DataFrame型の操作
DataFrame型にすると、様々な操作を行うことができます。
列名を表示、列名を指定して表示
DataFrame型はcolumnsで列名を取得したり、列名を指定してその列だけを取得することができます。
data = [["akiyama", 100, 100],
["satou" , 75, 99]]
DF = pd.DataFrame(data, columns = ['Students', 'Science', 'Math'])
# 列名を表示
# DF.columns = Index(['Students', 'Science', 'Math'], dtype='object')
DF.columns
# 以下のようにすると、指定した列をSeries型で取得できる
# 0 akiyama
# 1 satou
# Name: Students, dtype: object
DF["Students"]
DF.Students
# 2列以上取得したい場合は、それらの列名をlist型にして指定する
# 2列以上取得する場合、DataFrame型で取得される
DF[["Students", "Math"]]
上記のDF[["Students", "Math"]]は、以下のようなDataFrame型となります。
Students | Math | |
---|---|---|
0 | akiyama | 100 |
1 | satou | 99 |
行数を指定して表示
DataFrame型のilocを使用することで、指定した行のみ取得することができます。
data = [["akiyama", 100, 100],
["satou" , 75, 99]]
DF = pd.DataFrame(data, columns = ['Students', 'Science', 'Math'])
# 以下のようにすると、指定した行をSeries型で取得できる
# 行番号は「0」から始まることに注意
# Students satou
# Science 75
# Math 99
# Name: 1, dtype: object
DF.iloc[1]
# 2行以上取得したい場合は、取得したい範囲をスライスで記述
# 2行以上取得する場合、DataFrame型で取得される
DF.iloc[0:2]
上記のDF.iloc[0:2]は、以下のようなDataFrame型となります。
Students | Science | Math | |
---|---|---|---|
0 | akiyama | 100 | 100 |
1 | satou | 75 | 99 |
先頭だけを表示、最後だけ表示
DataFrame型の*head()*で先頭だけを表示、*tail()*で最後だけ表示させることができます。
data = [["akiyama", 100, 100],
["satou" , 75, 99]]
DF = pd.DataFrame(data, columns = ['Students', 'Science', 'Math'])
# 引数なしの場合は、先頭の5行まで表示
# 引数に行数を指定すると、先頭から指定した行数だけ表示
DF.head()
DF.head(1)
# 引数なしの場合は、最後の5行を表示
# 引数に行数を指定すると、最後から指定した行数だけ表示
DF.tail()
DF.tail(1)
特定の列で新しくDataFrame型を作成
以下のように、DataFrame型の特定の列だけを使って、新たにDataFrame型を作成することができます。
data = [["akiyama", 100, 100],
["satou" , 75, 99]]
DF = pd.DataFrame(data, columns = ['Students', 'Science', 'Math'])
# DataFrame型「DF」の「Students」と「Math」だけを使って、新しいDataFrame型を作成
# 「columns」に行を指定しますが、存在しない列を指定した場合、その列のデータは全て「NaN」として作成される
DF_new = DataFrame(DF, columns=['Students', 'Math'])
上記のDF_newは、以下のようなDataFrame型となります。
Students | Math | |
---|---|---|
0 | akiyama | 100 |
1 | satou | 99 |
指定した行、または列を削除
DataFrame型の*drop()*を利用すると、指定した列・行が削除されたDataFrame型を取得することができます。
data = [["akiyama", 100, 100],
["satou" , 75, 99]]
DF = pd.DataFrame(data, columns = ['Students', 'Science', 'Math'])
# 行を削除する場合、削除する行のindexを指定(ラベル名が付いてる場合は、ラベル名を指定)
# indexは「0」から始まるため、この場合は2行目を削除
DF_drop_axis0 = DF.drop(1)
# 行を削除する場合、引数の「axis」に「1」を指定
# また、削除する列のindexを指定(列名が付いてる場合は、列名を指定)
# 列名が付いているので、列名「Science」を削除
DF_drop_axis1 = DF.drop("Science", axis=1)
上記ののDF_drop_axis0は、以下のようなDataFrame型となります。
Students | Science | Math | |
---|---|---|---|
0 | akiyama | 100 | 100 |
DF_drop_axis1は、以下のようなDataFrame型となります。
Students | Math | |
---|---|---|
0 | akiyama | 100 |
1 | satou | 99 |
列を追加
以下のように、DataFrame型に新しい列を追加することができます。
data = [["akiyama", 100, 100],
["satou" , 75, 99]]
DF = pd.DataFrame(data, columns = ['Students', 'Science', 'Math'])
# 列「English」を追加。初期値に「NaN」を指定。
DF['English'] = np.nan
Students | Science | Math | English | |
---|---|---|---|---|
0 | akiyama | 100 | 100 | NaN |
1 | satou | 75 | 99 | NaN |
また、Series型を利用して、列を追加することもできます。
data = [["akiyama", 100, 100],
["satou" , 75, 99]]
DF = pd.DataFrame(data, columns = ['Students', 'Science', 'Math'])
# English = 0 100
# 1 30
# dtype: int64
English = pd.Series([100, 30], index=[0, 1])
# Series側のindexと、DataFrame型のindexが一致した箇所にデータが挿入
# 一致するものがない場合は、「NaN」となる
DF['English'] = English
Students | Science | Math | English | |
---|---|---|---|---|
0 | akiyama | 100 | 100 | 100 |
1 | satou | 75 | 99 | 30 |
条件を満たすデータを表示
条件を満たすデータの判定、および条件を満たすデータを表示できます。
data = [["akiyama", 100, 100],
["satou" , 75, 99]]
DF = pd.DataFrame(data, columns = ['Students', 'Science', 'Math'])
# 「Science」、 「Math」について、80を超えるデータが存在するか判定
DF_80over = DF[["Science", "Math"]] > 80
# 「Science」が 80を超える行を表示
Science_80over = DF[DF['Science'] > 80]
上記ののDF_80overは、以下のようなDataFrame型となります。
| | Science | Math |
|:-:|:-:|:-:|:-:|
| 0 | True | True |
| 1 | False | True |
Science_80overは、以下のようなDataFrame型となります。
Students | Science | Math | |
---|---|---|---|
0 | akiyama | 100 | 100 |