7
8

More than 3 years have passed since last update.

Pandasの基礎

Posted at

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ファイルが存在する。

test.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
7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8