こんにちは。
産婦人科医で人工知能の研究をしているTommy(Twitter:@obgyntommy)です。
本記事ではPythonのライブラリの1つである pandas の計算処理について学習していきます。
pandasの使い方については、以下の記事にまとめていますので参照してください。
【Python】Pandasの使い方【基本から応用まで全て解説】
続きを見る
データを加工していると、DataFrameを頻用します。
例えば、DataFrame を新しく作ることがありますし、また、numpy
や dict
などのデータから DataFrame
を作ることもあります。
本記事では DataFrame の使い方を習得してを使いこなせるようになりましょう。
なお、Dataframeに関する公式ドキュメントは以下になります。
DataFrame — pandas 2.2.3 documentation
続きを見る
なお、pandas.Dataframeに関する公式ドキュメントは以下になります。
pandas.DataFrame — pandas 2.2.3 documentation
続きを見る
ここで本記事の学習到達目標です。
本記事の学習目標
- Dataframeの概要を知る
- 行名・列名を変更する際のメソッド
- 空のDataFrameを動的に追加する方法
- 空のDataFrameを高速に動的に追加する方法
今回は、これらの計算がしっかりできるように習得していきましょう。
DataFrame概要
DataFrameはエクセルやデータベースのような2次元の表データです。
index
(行)、columns
(列)、data
(データの値)で構成されています。
index
は行名(行ラベル)、columns
は列名(列ラベル)、data
は実際のデータの値を意味します。
data
の代わりに value
が用いられることもあります。
DataFrameとセットで出てくるのがSeriesです。
Series
は行や列の1次元のデータで、index
(行)、data
(データの値)で構成されています。
図の青枠のように、1列、1行分のデータです。
DataFrameを作ってみる
さっそく、DataFrameを色々な方法で作ってみましょう。
繰り返しになりますが、DataFrameはindex、columns、dataの構成です。
これらのデータがあれば、 DataFrameが作れます。
このデータを与え方の違いによって作り方が異なります。
下記のようなデータを作っていきましょう。
先に、pandasのライブラリを読み込んでおいてください。
In[]
1 | import pandas as pd |
listから作る
listからDataFrameを作りましょう。
各構成を list
で用意すれば、作ることができます。
それぞれの構成要素を用意してみましょう。
In[]
1 2 3 4 5 6 7 8 9 | # columnsとindex columns = ['商品', '単価', '個数'] index = ['A', 'B', 'C', 'E', 'F'] # data data = [['マスク', 100, 10], ['りんご', 120, 3], ['本', 1000, 1], ['ペン', 150, 5], ['スマフォ',50000, 1]] |
あとは、これをpd.DataFrameの引数に渡します。
In[]
1 2 3 4 5 6 | # DataFrame作成 df = pd.DataFrame(data=data, columns=columns, index=index) # データ確認 df.head() |
Out[]
index
、columns
は省略しても作れます。
In[]
1 2 3 4 | # DataFrame作成 df = pd.DataFrame(data=data) # データ確認 df.head() |
自動で、0,1,2,…が割り当てられます。
index
が 0, 1, 2…
で良い場合は、省略することも多いです。
numpyから作る
numpyから作ってみましょう。
list
と違いはありませんが、data
を numpy
にして、作ってみます。
In
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import numpy as np # columnsとindex columns = ['商品', '単価', '個数'] index = ['A', 'B', 'C', 'E', 'F'] # data data = np.array([['マスク', 100, 10], ['りんご', 120, 3], ['本', 1000, 1], ['ペン', 150, 5], ['スマフォ',50000, 1]]) # DataFrame作成 df = pd.DataFrame(data=data, columns=columns, index=index) # データ確認 df.head() |
同じ、結果になりますね。
dictから作る
dictで作ってみましょう。
dict
は辞書型と呼ばれるもので、key
値とデータがセットになっているものです。
dict
から作ると key
値が列名になります。
key
値を商品、単価、個数としています。
In[]
1 2 3 4 5 6 7 8 9 10 | # data data_dic = { '商品': ['マスク', 'りんご', '本', 'ペン', 'スマフォ'], '単価': [100, 120, 1000, 150, 50000], '個数': [10, 3, 1, 5, 1], } # DataFrame作成 df = pd.DataFrame(data=data_dic) # データ確認 |
Out[]
index
が自動割り当てされていますね。
index
が必要な場合は list
で割り当てることが可能です。
In[]
1 2 3 4 5 6 7 8 9 10 11 12 | index = ['A', 'B', 'C', 'E', 'F'] # data data_dic = { '商品': ['マスク', 'りんご', '本', 'ペン', 'スマフォ'], '単価': [100, 120, 1000, 150, 50000], '個数': [10, 3, 1, 5, 1], } # DataFrame作成 df = pd.DataFrame(data=data_dic, index=index) # データ確認 df.head() |
ただ、これだとデータの dict
と index
を別に持っていることになります。
データが別の場合、使いにくいですし、バグも出やすくなるでしょう。
どちらかというと、商品IDというデータが dict
に含まれている方が自然です。
In[]
1 2 3 4 5 6 7 | # data data_dic = { '商品': ['マスク', 'りんご', '本', 'ペン', 'スマフォ'], '単価': [100, 120, 1000, 150, 50000], '個数': [10, 3, 1, 5, 1], '商品ID': ['A', 'B', 'C', 'E', 'F'], } |
このデータで DataFrame
を作ります。
In[]
1 2 3 4 | # DataFrame作成 df = pd.DataFrame(data=data_dic) # データ確認 df.head() |
Out[]
商品IDが列としてデータになっているので、これをset_indexメソッドで「商品ID」列をindexにします。
In[]
1 2 3 4 | # 商品IDをindexに df = df.set_index('商品ID') # データ確認 df.head() |
Out[]
一応、indexになっているかも確認してみましょう。
In[]
1 | df.index |
Out[]
1 | Index(['A', 'B', 'C', 'E', 'F'], dtype='object', name='商品ID') |
商品IDが index
になっています。
少し、ごちゃごちゃしてきますが、index
も辞書で指定すると、一気に設定できます。
In[]
1 2 3 4 5 6 7 8 9 10 11 | # data data_dic = { '商品': {'A':'マスク', 'B':'りんご', 'C':'本', 'D':'ペン', 'E':'スマフォ'}, '単価': {'A':100, 'B':120, 'C':1000, 'D':150, 'E':50000}, '個数': {'A':10, 'B':3, 'C':1, 'D':5, 'E':1}, } # DataFrame作成 df = pd.DataFrame(data=data_dic) # データ確認 df.head() |
jsonから作る
jsonも辞書型に似ていますが、java script とかweb APIのやり取りで使う文字列です。
記述方法は dict
と同じで {}
が辞書、[]
が配列になります。
dict
でも説明した、商品IDを index
にする方法と、columns
と index
を一気に設定する方法を説明します。
まず、商品ID列を用意したデータを使います。
*python
で文字列を複数行で扱う時は、”””
(ダブルコーテーション3つ)で囲みます。
In[]
1 2 3 4 5 6 7 8 9 10 11 12 13 | data = """ { "商品ID":["A", "B", "C", "D", "E"], "商品":["マスク", "りんご", "本", "ペン", "スマフォ"], "単価":[100, 120, 1000, 150, 50000], "個数":[10, 3, 1, 5, 1] } """ df = pd.read_json(data) # 商品IDをindexに df = df.set_index('商品ID') #データ確認 df.head() |
Out[]
次は、columns
と index
を一気に指定します。
In[]
1 2 3 4 5 6 7 8 9 | data = """ { "商品":{"A":"マスク", "B":"りんご", "C":"本", "D":"ペン", "E":"スマフォ"}, "単価":{"A":100, "B":120, "C":1000, "D":150, "E":50000}, "個数":{"A":10, "B":3, "C":1, "D":5, "E":1} } """ df = pd.read_json(data) df.head() |
Out[]
行名、列名を変更するメソッドの扱い方
columns
と index
を変更するにはrenameメソッドを使います。
データは同じものを使っていくので、下記を都度読み直して、実行していってください。
In[]
1 2 3 4 5 6 7 8 9 | data = """ { "商品":{"A":"マスク", "B":"りんご", "C":"本", "D":"ペン", "E":"スマフォ"}, "単価":{"A":100, "B":120, "C":1000, "D":150, "E":50000}, "個数":{"A":10, "B":3, "C":1, "D":5, "E":1} } """ df = pd.read_json(data) df.head() |
Out[]
1つずつ行名・列名を変更する場合
列名を変更する場合は、パラメータ「columns
」で変更します。
渡すデータは辞書型と同じ形式で、{‘変更前’: ‘変更後’}
を渡します。
columns
「商品」を英語の「product
」にします。
In[]
1 2 | df = df.rename(columns={'商品':'product'}) df.head() |
Out[]
行名を変更する場合は、パラメータ「index
」で変更します。
index「A」を小文字の「a」にします。
In[]
1 2 | df = df.rename(index={'A':'a'}) df.head() |
Out[]
複数の行名・列名を変更する場合
まとめて変更する場合は、{‘変更前’: ‘変更後’, ‘変更前’: ‘変更後’, …}
と増やしていきます。
columns
をすべて英語に表記にしましょう。
In[]
1 2 | df = df.rename(columns={'商品':'product', '単価':'price', '個数':'num'}) df.head() |
Out[]
接頭に文字追加する場合
列名の頭に文字列追加していきましょう。
add_prefixメソッドを使います。引数に追加する文字列を渡します。
列名の頭に「 x_
」を付けます。
In[]
1 2 | df = df.add_prefix('x_') df.head() |
これは例えば、処理前、処理後のデータがあったときに、比較するために2つのDataFrameを1つにするとします。
その時、接頭、接尾に文字列を追加することでわかりやすくします。
接尾に文字追加する場合
列名の末に文字列追加していきましょう。
add_suffixメソッドを使います。引数に追加する文字列を渡します。
末尾に「 _y
」をつけましょう。
In[]
1 2 | df = df.add_suffix('_y') df.head() |
Out[]
空のDataFrameを動的に追加する
list
などからデータを追加するのではなく、空の DataFrame
を作って、for
文で1行ずつデータを追加してみましょう。
まず、空の DataFrame
を作ります。
data
を渡さず、列名だけ渡すことで作れます。
In[]
1 2 3 | # 空のDataFrame df = pd.DataFrame(columns=['商品', '単価', '個数']) df.head() |
Out[]
あとは、1行ずつデータを追加します。
DataFrameのappendメソッドを使って、引数にSeriesを渡すことで追加できます。
振り返りになりますが、Seriesはdataとindexを持つ1次元のデータです。
今回は、1行ずつのデータを作っては、追加します。
まず、1行分のSeriesデータを作ってみましょう。
In[]
1 2 | se = pd.Series(['マスク', 100, 10], index=df.columns) se |
Out[]
df.columns
で列名を取得できるので、それを index
として渡しています。
Series
は1次元なので index
を指定しますが、空の DataFrame
には columns
として入ります。
では、for文でデータを追加していきましょう。
appendメソッド
に、ignore_index=True
とすることで、index
が自動で数値が割り当てられます。
In[]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # 追加するデータ data = [['マスク', 100, 10], ['りんご', 120, 3], ['本', 1000, 1], ['ペン', 150, 5], ['スマフォ',50000, 1]] # for文でデータを順に追加 for product, price, num in data: # 1行のSeriesを作成 se = pd.Series([product, price, num], index=df.columns) # appendメソッドで追加 df = df.append(se, ignore_index=True) # データ確認 df.head() |
Out[]
空のDataFrameを動的に追加する(高速)
先ほどの append
を使った方法は、何万行と追加すると処理が遅くなります。
何万行といったデータを動的に追加する場合には、いったん dict
にデータを入れて、後で dict
のデータを DataFrame
にすると高速にできます。
dict
のキー値は 0, 1, 2…
で追加していきます。
まず、1行ずつの Series
データを dict
に入れてみましょう。
In[]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 空のDataFrame df = pd.DataFrame(columns=['商品', '単価', '個数']) # 追加するデータ data = [['マスク', 100, 10], ['りんご', 120, 3], ['本', 1000, 1], ['ペン', 150, 5], ['スマフォ',50000, 1]] # 空のdict 一時的にSeriesのデータをいれる dict_tmp = {} # for文でデータを順に追加 for ind, (product, price, num) in enumerate(data): # 1行のSeriesを作成 se = pd.Series([product, price, num], index=df.columns) # dictに追加 dict_tmp[ind] = se dict_tmp |
0,1,2…をキーとして、値にSeriesのデータを入れました。
このデータを、from_dictメソッドで変換します。
パラメータ「orient
」に’columns’
、’index’
を渡すことで、キー値がどちらで使う指定できます。
今回は、orient = ‘index’
とします。
In[]
1 2 3 | df = df.from_dict(dict_tmp, orient="index") # データ確認 df.head() |
Out[]
これで、高速にDataFrameが作れました。
おまけ
どれだけ高速化、比較してみましょう。
append
を使った方で、1000回ループします。
In[]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # 空のDataFrame df = pd.DataFrame(columns=['商品', '単価', '個数']) # 追加するデータ data = [['マスク', 100, 10], ['りんご', 120, 3], ['本', 1000, 1], ['ペン', 150, 5], ['スマフォ',50000, 1]] start = time.time() # for文でデータを順に追加 for i in range(1000): for product, price, num in data: # 行のシリーズを作成 se = pd.Series([product, price, num], index=df.columns) # appendメソッドで追加 df = df.append(se, ignore_index=True) elapsed_time = time.time() - start print ("elapsed_time:{0}".format(elapsed_time) + "[sec]") # データ確認 df.head() |
Out[]
1 | elapsed_time:9.50581669807434[sec] |
高速な方法
In[]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # 空のDataFrame df = pd.DataFrame(columns=['商品', '単価', '個数']) # 追加するデータ data = [['マスク', 100, 10], ['りんご', 120, 3], ['本', 1000, 1], ['ペン', 150, 5], ['スマフォ',50000, 1]] # 一時的なデータおきば dict_tmp = {} start = time.time() # for文でデータを順に追加 for i in range(1000): # for文でデータを順に追加 for ind, (product, price, num) in enumerate(data): # 行のシリーズを作成 se = pd.Series([product, price, num], index=df.columns) # appendメソッドで追加 dict_tmp[ind] = se elapsed_time = time.time() - start print ("elapsed_time:{0}".format(elapsed_time) + "[sec]") df = df.from_dict(dict_tmp, orient="index") # データ確認 df.head() |
Out[]
1 | elapsed_time:0.4443683624267578[sec] |
データによると思いますが、今回は約20倍くらいの差があります。
また、pandas の使用方法については以下の記事にまとめています。一通り本記事でpandasでDataframe使用する方法を学習できた方は再度復習してみましょう。
【Python】Pandasの使い方【基本から応用まで全て解説】
続きを見る
人気記事 【入門から上級レベルまで】人工知能・機械学習の独学におすすめの本25選
人気記事 無料あり:機械学習エンジニアの僕がおすすめするAI(機械学習)特化型プログラミングスクール3社