らくがき入門

機械学習を始めとしたコンピュータサイエンスを主に扱っています。

pandasを用いてフラグがついている列が先頭になるように行ごとにシフトする

やりたい処理は、すべての行でフラグ1が先頭にくるようにシフトしたい。

うまいやり方かどうかわからないけど、一応うまくいっているような気がする。

サンプルコード

import numpy as np
from numpy import nan
import pandas as pd
import warnings 
warnings.filterwarnings("ignore") # 実行に関係のない警告を非表示
# 左からゼロパディング
columns_list = ["a_{0:02d}".format(i) for i in range(0, 12)]
value_arr = np.array([[nan, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
                      [nan, nan, 1, 0, 0, nan, nan, nan, nan, nan, nan, nan], 
                      [nan, nan, nan, 1, 0, 0, 0, nan, nan, nan, nan, nan] 
                     ])

時系列のデータを想定したDataFrameを作成。

フラグが1になるカラムが行ごとにバラバラなので、すべての行で先頭のカラムが1になるようにシフトしたい。

df = pd.DataFrame(value_arr, columns=columns_list)
df
a_00 a_01 a_02 a_03 a_04 a_05 a_06 a_07 a_08 a_09 a_10 a_11
0 NaN 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
1 NaN NaN 1.0 0.0 0.0 NaN NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN 1.0 0.0 0.0 0.0 NaN NaN NaN NaN NaN

行ごとに処理を行う。

  1. 各行ごとにフラグ1がくるインデックスを取得して、その分だけ左方向にシフトする(作成されるのはSeries)

  2. 作成されたseriesを行方向に結合する

  3. 結合してできたDataFrameをtransposeして元のDataframeと形を揃える。

se_concat = pd.concat([df.ix[i].shift(val) for i, val 
                       in enumerate([-np.where(value_arr == 1)[1][j] 
                                     for j in range(len(df))])], axis=1)
se_concat.T
a_00 a_01 a_02 a_03 a_04 a_05 a_06 a_07 a_08 a_09 a_10 a_11
0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 NaN
1 1.0 0.0 0.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 1.0 0.0 0.0 0.0 NaN NaN NaN NaN NaN NaN NaN NaN

参考にした書籍・サイト

Pythonによるデータ分析入門 第2版 ―NumPy、pandasを使ったデータ処理

Pythonによるデータ分析入門 第2版 ―NumPy、pandasを使ったデータ処理

<Python, pandas> 縦にずらす。