2018/7/22 プログラミング, Python, データ分析
Excelは使いやすく、直感的で便利なソフトですが、とにかく手作業が多い。フィルターをかけたり、欠損値を消したり、ピボットテーブルを作成したりとすべてかなりの手数がかかります。pythonのライブラリのpandasを使えば、そんな操作を1行のコマンドだけですぐに実行することができます。また、NumpyやMatplotlib、SciPy、BeautifulSoup、TensorFlowなど様々なライブラリと連携を行い、回帰分析・決定木やクラスタリング・スクレイピング・ディープラーニングまで複雑な分析や予測モデルの構築まで対応することができます。今回は自分の備忘録も兼ねてpandas公式サイトのdocumentationを参考に基本となる操作をまとめてみました。
目次 [非表示]
配列の作成
1次元配列(Series)
単純な配列です。indexは指定しなくても自動で連番が振られます。
1
2
3
4
5
6
7
8
9
|
>>> s = pd.Series([1,3,5,np.nan,6,8])
>>> s
0 1.0
1 3.0
2 5.0
3 NaN
4 6.0
5 8.0
dtype: float64
|
2次元配列(DataFrame)
excelのセルに入力するようなイメージです。下記の例ではindexとcolumnは指定しています。
1
2
3
4
5
6
7
8
9
10
|
>>> dates = pd.date_range('20130101', periods=6)
>>> df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
>>> df
A B C D
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
2013-01-05 -0.424972 0.567020 0.276232 -1.087401
2013-01-06 -0.673690 0.113648 -1.478427 0.524988
|
下記の例ではdict形式でDataFrameに数値を入力しています。
1
2
3
4
5
6
7
|
>>> df2 = pd.DataFrame({ 'A' : 1.,'B' : pd.Timestamp('20130102'),'C' : pd.Series(1,index=list(range(4)),dtype='float32'),'D' : np.array([3] * 4,dtype='int32'),'E' : pd.Categorical(["test","train","test","train"]),'F' : 'foo' })
>>> df2
A B C D E F
0 1.0 2013-01-02 1.0 3 test foo
1 1.0 2013-01-02 1.0 3 train foo
2 1.0 2013-01-02 1.0 3 test foo
3 1.0 2013-01-02 1.0 3 train foo
|
dtypesでcolumnデータの型を調べることができます。
1
2
3
4
5
6
7
8
|
>>> df2.dtypes
A float64
B datetime64[ns]
C float32
D int32
E category
F object
dtype: object
|
データの閲覧と整理
pandasならコマンド一つで、見たいデータにスマートにアクセスできます。
閲覧
最初・最後の行の一部のみ表示
1
2
3
4
5
6
7
8
9
10
11
12
|
>>> df.head()
A B C D
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
2013-01-05 -0.424972 0.567020 0.276232 -1.087401
>>> df.tail(3)
A B C D
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
2013-01-05 -0.424972 0.567020 0.276232 -1.087401
2013-01-06 -0.673690 0.113648 -1.478427 0.524988
|
index・column名・データの型を出力、値の確認
1
2
3
4
5
6
7
8
9
10
11
|
>>> df.index
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04','2013-01-05', '2013-01-06'],dtype='datetime64[ns]', freq='D')
>>> df.columns
Index(['A', 'B', 'C', 'D'], dtype='object')
>>> df.values
array([[ 0.4691, -0.2829, -1.5091, -1.1356],
[ 1.2121, -0.1732, 0.1192, -1.0442],
[-0.8618, -2.1046, -0.4949, 1.0718],
[ 0.7216, -0.7068, -1.0396, 0.2719],
[-0.425 , 0.567 , 0.2762, -1.0874],
[-0.6737, 0.1136, -1.4784, 0.525 ]])
|
データの統計も一発です。
1
2
3
4
5
6
7
8
9
10
|
>>> df.describe()
A B C D
count 6.000000 6.000000 6.000000 6.000000
mean 0.073711 -0.431125 -0.687758 -0.233103
std 0.843157 0.922818 0.779887 0.973118
min -0.861849 -2.104569 -1.509059 -1.135632
25% -0.611510 -0.600794 -1.368714 -1.076610
50% 0.022070 -0.228039 -0.767252 -0.386188
75% 0.658444 0.041933 -0.034326 0.461706
max 1.212112 0.567020 0.276232 1.071804
|
行列の入れ替え
1
2
3
4
5
6
|
>>> df.T
2013-01-01 2013-01-02 2013-01-03 2013-01-04 2013-01-05 2013-01-06
A 0.469112 1.212112 -0.861849 0.721555 -0.424972 -0.673690
B -0.282863 -0.173215 -2.104569 -0.706771 0.567020 0.113648
C -1.509059 0.119209 -0.494929 -1.039575 0.276232 -1.478427
D -1.135632 -1.044236 1.071804 0.271860 -1.087401 0.524988
|
ソート
軸でソート
1
2
3
4
5
6
7
8
|
>>> df.sort_index(axis=1, ascending=False)
D C B A
2013-01-01 -1.135632 -1.509059 -0.282863 0.469112
2013-01-02 -1.044236 0.119209 -0.173215 1.212112
2013-01-03 1.071804 -0.494929 -2.104569 -0.861849
2013-01-04 0.271860 -1.039575 -0.706771 0.721555
2013-01-05 -1.087401 0.276232 0.567020 -0.424972
2013-01-06 0.524988 -1.478427 0.113648 -0.673690
|
値でソート
1
2
3
4
5
6
7
8
|
>>> df.sort_values(by='B')
A B C D
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-06 -0.673690 0.113648 -1.478427 0.524988
2013-01-05 -0.424972 0.567020 0.276232 -1.087401
|
データの選択
直接指定
列の選択
1
2
3
4
5
6
7
8
|
>>> df['A']
2013-01-01 0.469112
2013-01-02 1.212112
2013-01-03 -0.861849
2013-01-04 0.721555
2013-01-05 -0.424972
2013-01-06 -0.673690
Freq: D, Name: A, dtype: float64
|
行の選択、スライスも使える
1
2
3
4
5
6
7
8
9
10
|
>>> df[0:3]
A B C D
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
>>> df['20130102':'20130104']
A B C D
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
|
ラベルでの選択(loc)、スカラの場合(at)で高速化
下記の例では第一引数で行の指定(スライスも可能、今回はすべての行)、第二引数で列の指定しています。
1
2
3
4
5
6
7
8
|
>>> df.loc[:,['A','B']]
A B
2013-01-01 0.469112 -0.282863
2013-01-02 1.212112 -0.173215
2013-01-03 -0.861849 -2.104569
2013-01-04 0.721555 -0.706771
2013-01-05 -0.424972 0.567020
2013-01-06 -0.673690 0.113648
|
行番号での選択(iloc)、スカラの場合(iat)で高速化
下記の例では第一引数で行の指定(スライスも可能、「,」で番号を指定で串刺し選択も可能)、第二引数で列の指定しています。
1
2
3
4
5
6
7
8
9
|
>>> df.iloc[3:5,0:2]
A B
2013-01-04 0.721555 -0.706771
2013-01-05 -0.424972 0.567020
>>> df.iloc[[1,2,4],[0,2]]
A C
2013-01-02 1.212112 0.119209
2013-01-03 -0.861849 -0.494929
2013-01-05 -0.424972 0.276232
|
関係演算子を使った指定
数値の大小で選択
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> df[df.A > 0]
A B C D
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632
2013-01-02 1.212112 -0.173215 0.119209 -1.044236
2013-01-04 0.721555 -0.706771 -1.039575 0.271860
>>> df[df > 0]
A B C D
2013-01-01 0.469112 NaN NaN NaN
2013-01-02 1.212112 NaN 0.119209 NaN
2013-01-03 NaN NaN NaN 1.071804
2013-01-04 0.721555 NaN NaN 0.271860
2013-01-05 NaN 0.567020 0.276232 NaN
2013-01-06 NaN 0.113648 NaN 0.524988
|
フィルタを使った指定
文字列でフィルタをかける(isin)。文字通りexcelのフィルタのような処理ができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
>>> df2 = df.copy()
>>> df2['E'] = ['one', 'one','two','three','four','three']
>>> df2
A B C D E
2013-01-01 0.469112 -0.282863 -1.509059 -1.135632 one
2013-01-02 1.212112 -0.173215 0.119209 -1.044236 one
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804 two
2013-01-04 0.721555 -0.706771 -1.039575 0.271860 three
2013-01-05 -0.424972 0.567020 0.276232 -1.087401 four
2013-01-06 -0.673690 0.113648 -1.478427 0.524988 three
#ここまでデータ準備
>>> df2[df2['E'].isin(['two','four'])]
A B C D E
2013-01-03 -0.861849 -2.104569 -0.494929 1.071804 two
2013-01-05 -0.424972 0.567020 0.276232 -1.087401 four
|
欠損値
データ分析において一番やっかいなのが欠損値の処理です。欠損値を正しく処理しないと現実とはかけ離れた結論を導いてしまいます。pandasなら簡単に処理方法を指定できます。
欠損値の存在する行を省いて表示
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])
>>> df1.loc[dates[0]:dates[1],'E'] = 1
>>> df1
A B C D F E
2013-01-01 0.000000 0.000000 -1.509059 5 NaN 1.0
2013-01-02 1.212112 -0.173215 0.119209 5 1.0 1.0
2013-01-03 -0.861849 -2.104569 -0.494929 5 2.0 NaN
2013-01-04 0.721555 -0.706771 -1.039575 5 3.0 NaN
#ここまでデータ準備
>>> df1.dropna(how='any')
A B C D F E
2013-01-02 1.212112 -0.173215 0.119209 5 1.0 1.0
|
欠損値を指定値で埋めて出力
1
2
3
4
5
6
|
>>> df1.fillna(value=5)
A B C D F E
2013-01-01 0.000000 0.000000 -1.509059 5 5.0 1.0
2013-01-02 1.212112 -0.173215 0.119209 5 1.0 1.0
2013-01-03 -0.861849 -2.104569 -0.494929 5 2.0 5.0
2013-01-04 0.721555 -0.706771 -1.039575 5 3.0 5.0
|
欠損値であるかないかbooleanで判定
1
2
3
4
5
6
|
>>> pd.isna(df1)
A B C D F E
2013-01-01 False False False False True False
2013-01-02 False False False False False False
2013-01-03 False False False False False True
2013-01-04 False False False False False True
|
0 コメント:
コメントを投稿