Python pandas DataFrame tips

Table of Content

pandas DataFrameをdfとして用意します

[cc lang='python']
>>> import pandas as pd
>>> import numpy as np
>>> from datetime import datetime

>>> index = list(range(0,4))
>>> depth = [3.7, -4.8, 6.2, 6.6]
>>> lat = [35.462329, 35.461878, 35.461878, 35.461878]
>>> lon = [139.875752, 139.875751, 139.876302, 139.876853]
>>> mask = [1, 0, 1, 1]
>>> df = pd.DataFrame({"Depth": depth, "Lat": lat, "Lon": lon, "mask": mask}, index=index)
>>> df

Depth Lat Lon mask
0 3.7 35.462329 139.875752 1
1 -4.8 35.461878 139.875751 0
2 6.2 35.461878 139.876302 1
3 6.6 35.461878 139.876853 1
[/cc]

列Lonをデータフレームとして取り出します

複数の列を取り出すには[cci_python]df[['Lon', 'mask']][/cci]のようにリストを渡します.[cci_python]df['Lon', 'mask'][/cci]はエラーとなります.
[cc lang='python']
>>> df[['Lon']]

Lon
0 139.875752
1 139.875751
2 139.876302
3 139.876853
[/cc]
ただし,1列だけ抽出するには,[cci_python]df['Lat'][/cci]あるいは[cci_python]df.Lat[/cci]とすることもできます.これらの場合は[cci_python]DataFrame[/cci]ではなく,[cci_python]Series[/cci]になることに注意が必要です.DataFrameのみを想定しているスクリプトでSeriesが現れるとエラーとなる,わかりにくいバグに注意しましょう.

Depth列が負の値の行を抽出するには条件式を与えます

[cc lang='python']
>>> df[df.Depth < 0] Depth Lat Lon mask 1 -4.8 35.461878 139.875751 0 [/cc] [cci_python]df[df['Depth'] < 0][/cci]でも同じです.[cci_python]mask==1[/cci]を抽出するには同様に[cci_python]df[df['mask'] == 1][/cci]とします.一方,条件式をDataFrameとして抽出すると(カギ括弧をさらに増やす),以下のようになるので,注意が必要です. [cc lang='python'] >>> df[df[['Depth']] < 0] Depth Lat Lon mask 0 NaN NaN NaN NaN 1 -4.8 NaN NaN NaN 2 NaN NaN NaN NaN 3 NaN NaN NaN NaN [/cc]

列を追加するには列名を指定してリストを代入します

[cc lang='python']
>>> stn=["A","B","C","D"]
>>> df['stn'] = stn
>>> df

Depth Lat Lon mask stn
0 3.7 35.462329 139.875752 1 A
1 -4.8 35.461878 139.875751 0 B
2 6.2 35.461878 139.876302 1 C
3 6.6 35.461878 139.876853 1 D
[/cc]

列を削除するにdf.drop(['列名'], axis=1)とします

[cc lang='python']
>>> df.drop(['stn'], axis=1)

Depth Lat Lon mask
0 3.7 35.462329 139.875752 1
1 -4.8 35.461878 139.875751 0
2 6.2 35.461878 139.876302 1
3 6.6 35.461878 139.876853 1
[/cc]
列名はリストとして与えます.[cci_python]axis=1[/cci]は列への適用を意味し,[cci_python]axis=0[/cci](デフォルト)は行への適用です.また,[cci_python]df[/cci]に反映させるには,[cci_python]df.drop('列名', axis=1, inplace=True)[/cci]のように[cci_python]inplace=True[/cci]が必要です.

日付時刻文字の列を追加し,datetimeオブジェクトとして認識させます

[cc_python]
>>> dt = ["2018-01-02 11:00:00", "2018-03-05 00:00:00", "2018-04-01 16:42:31", "2018-05-13 12:15:30"]
>>> df['datetime'] = pd.to_datetime(dt)

Depth Lat Lon mask datetime
0 3.7 35.462329 139.875752 1 2018-01-02 11:00:00
1 -4.8 35.461878 139.875751 0 2018-03-05 00:00:00
2 6.2 35.461878 139.876302 1 2018-04-01 16:42:31
3 6.6 35.461878 139.876853 1 2018-05-13 12:15:30
[/cc]
さらに,今追加した[cci_python]datetime[/cci]列を[cci_python]index[/cci]にします.
[cc_python]
>>> df.set_index('datetime')

Depth Lat Lon mask
datetime
2018-01-02 11:00:00 3.7 35.462329 139.875752 1
2018-03-05 00:00:00 -4.8 35.461878 139.875751 0
2018-04-01 16:42:31 6.2 35.461878 139.876302 1
2018-05-13 12:15:30 6.6 35.461878 139.876853 1
[/cc]
[cci_python]df[/cci]を更新するには[cci_python]inplace=True[/cci]が必要です.

日付時刻の期間の文字列で行を抽出します

[cc_python]
>>> df["2018-02":"2018-04"]

Depth Lat Lon mask
datetime
2018-03-05 00:00:00 -4.8 35.461878 139.875751 0
2018-04-01 16:42:31 6.2 35.461878 139.876302 1
[/cc]
この例では2018年2月から4月の期間で切り出しています.[cci_python]df[1:3][/cci]のようにリストのスライスで抽出することもできます.

df.iloc[行index, 列index]でスライスします

[cc_python]
>>> df.iloc[1:3, 1:3]

Lat Lon
datetime
2018-03-05 00:00:00 35.461878 139.875751
2018-04-01 16:42:31 35.461878 139.876302
[/cc]
行と列のインデックスでスライスします.[cci_python]df.iloc[1:3, 1][/cci]と[cci_python]df.iloc[1:3, 1:2][/cci]は共に2行1列を抽出しますが,前者は[cci_python]Series[/cci]に,後者は[cci_python]DataFrame[/cci]になる点に注意しましょう.

df.loc[行名, [列名]]でスライスします

[cc_python]
>>> df.loc["2018-01-01":"2018-01-31", ['Depth']]

Depth
datetime
2018-01-02 11:00:00 3.7
[/cc]
インデックスではなく行名,列名でスライスします.列が1つだけでもリストで与えると[cci_python]DataFrame[/cci]を返します.スライスした要素(3.7)に値(0.0)を代入すると置換されます.
[cc_python]
>>> df.loc["2018-01-01":"2018-01-31", ['Depth']] = 0.0
>>> df

Depth Lat Lon mask
datetime
2018-01-02 11:00:00 0.0 35.462329 139.875752 1
2018-03-05 00:00:00 -4.8 35.461878 139.875751 0
2018-04-01 16:42:31 6.2 35.461878 139.876302 1
2018-05-13 12:15:30 6.6 35.461878 139.876853 1
[/cc]

df.replace([置換前の値], 置換後の値)で値(または値のリスト)を置換します

[cc_python]
>>> df.replace([-4.8], -1.0)

Depth Lat Lon mask
datetime
2018-01-02 11:00:00 0.0 35.462329 139.875752 1
2018-03-05 00:00:00 -1.0 35.461878 139.875751 0
2018-04-01 16:42:31 6.2 35.461878 139.876302 1
2018-05-13 12:15:30 6.6 35.461878 139.876853 1
[/cc]
より明確に,[cci_python]df.replace(to_replace=[-4.8], value = -1.0)[/cci]でも大丈夫です.リストなので複数の値を同時に置換できます.データフレームを更新するには[cci_python]inplace=True[/cci]が必要です.また,[cci_python]df.replace()[/cci]では条件式を使うとはまるので,避けた方がよいでしょう(こちらに解説があります).

df.mask(条件式, 置換する値)で条件式を満たす要素の値を置換します

[cc_python]
>>> df['Depth'].mask(df['Depth'] < 0, np.nan, inplace=True) Depth Lat Lon mask datetime 2018-01-02 11:00:00 0.0 35.462329 139.875752 1 2018-03-05 00:00:00 NaN 35.461878 139.875751 0 2018-04-01 16:42:31 6.2 35.461878 139.876302 1 2018-05-13 12:15:30 6.6 35.461878 139.876853 1 [/cc] [cci_python]Depth列[/cci]が負の値を欠損値として[cci_python]NaN[/cci]に置換しました.データフレーム自体を更新するには第3引数に[cci_python]inplace=True[/cci]を指定します.[cci_python]df[['Depth']][/cci]のように[cci_python]DataFrame[/cci]で切り出しても問題ありません.

列の順番を入れ替えるには列名のリストを渡します

[cc_python]
>>> df[['Lat', 'Lon', 'Depth', 'mask']]

Lat Lon Depth mask
datetime
2018-01-02 11:00:00 35.462329 139.875752 0.0 1
2018-03-05 00:00:00 35.461878 139.875751 NaN 0
2018-04-01 16:42:31 35.461878 139.876302 6.2 1
2018-05-13 12:15:30 35.461878 139.876853 6.6 1
[/cc]

要素がobjectのDataFrameを用意します

見た目は数値でありながら,objectとなっている場合に,数値として扱う方法です.
[cc_python]
>>> num_str = ['1.0', '2.0', '3.0', '4.0']
>>> df['num_str'] = num_str
>>> df

Depth Lat Lon mask num_str
datetime
2018-01-02 11:00:00 0.0 35.462329 139.875752 1 1.0
2018-03-05 00:00:00 NaN 35.461878 139.875751 0 2.0
2018-04-01 16:42:31 6.2 35.461878 139.876302 1 3.0
2018-05-13 12:15:30 6.6 35.461878 139.876853 1 4.0

>>> df['num_str'].values
array(['1.0', '2.0', '3.0', '4.0'], dtype=object)
[/cc]
見た目では分かりませんが,[cci_python]num_str列[/cci]の[cci_python]dtype[/cci]は[cci_python]object[cci]です.なお,[cci_python].values[/cci]で[cci_python]Series[/cci]を[cci_python]numpy[/cci]の[cci_python]array[/cci]に変換しています.[cci_python]df[['num_str']][/cci]とすると[cci_python]DataFrame[/cci]となり,これに[cci_python].values[/cci]を適用すると,リストを要素にもつリストとなって,扱いにくくなります.

.astype()で実数に変換します

[cc_python]
>>> df['num_str'].astype(np.float64).values
array([1., 2., 3., 4.])
[/cc]
実数の[cci_python]numpy array[/cci]に変換されました.データフレームを更新するには代入します.
[cc_python]
>>> df['num_str'] = df['num_str'].astype(np.float64)
[/cc]
[cci_python]Series[/cci]で扱いましたが,二重のカギ括弧にして[cci_python]DataFrame[/cci]としても大丈夫です.

コピーの注意

DataFrameのコピーは要注意です.[cci_python]df2=df[/cci]はコピーではありません!
[cc lang="python"]
>>> df2 = df
[/cc]
として,df2を変更しますと,dfも同時に変更されてしまいます.dfを変更せずに残しておいたつもりになっていると,不可思議な挙動に悩まされることになります.コピーをするには以下のようにします.
[cc lang="python"]
>>> df2 = df.copy()
[/cc]
このような違いはdeep copyとshallow copyの違いです.[cci_python]df2=df.copy()[/cci]はdeep copy,[cci_python]df2=df[/cci]はshallow copyになります.[cci_python].copy()[/cci]メソッドは引数をとり,[cci_python].copy(deep=False)[/cci]とするとshallow copyになり,[cci_python].copy(deep=True)[/cci]とするとdeep copyになります.デフォルトはdeep copyです.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください