すごいPandasさっくり学ぼう
はじめに
Pandas
とはプログラミング言語Python
において、データ解析を支援する機能を提供するライブラリです1。Pandas
はPython
のライブラリでも複雑だと思います2。 しかし、その分、自由度が非常に高く、データ分析やさんにとって、Pandas
なしでのデータ分析は考えられません。そこで、「ここまで理解しとけば、あとは(他サイトとかみたら)どうにでもなるわ」ってところまで説明したいと思います3。
攻略方法
\1. 準備
-
numpy
(1次元)のインデックス参照、スライシング、ブールインデックス参照、ファンシーインデックス参照を使えるようにする -
numpy
(2次元)のインデックス参照、スライシング、ブールインデックス参照を使えるようにする。numpy.iloc_
関数の挙動を理解する。(ファンシーインデックス参照は2次元でのndarrayでは使いづらい仕様になっているので、個人的にはほとんど使わない)
\2. Pandas
入門
-
Series, DataFrame
の作成、インデックス参照を使えるようにする(Series
は基本的にnumpy
(1次元)の拡張。DataFrame
は基本的にdf.loc
(ラベル名優先)またはdx.iloc
(番号優先)を用いれば基本的にnumpy
(2次元)の拡張。) -
Series, DataFrame
のデータ追加、抽出、削除、修正などをできるようにする -
(
Series, DataFrame
内の要素やindex名が文字列なら、抽出や修正の一括操作が可能。便利なので、Pandas
のstr
アクセサによる文字列処理を理解する)
ぐらいまでやっておくと、あとは軌道に乗って自分でいろいろ調べられるレベルに到達するはず(groupby
とかも[1]とかでスムーズに理解できるはず)。
- 全体を通して言えるのが、特に演算後のdimension(次元)がいくつなの?ということをコードを書く際に常に意識することが大事だと思います。
例えば、Numpy
なら、
arr = np.arange(12) # arrは1次元のndarray
arr = arr.reshape(3,4) # arrは2次元のndarrary
# arr[i,j]の第一要素は行、第2要素は列
arr[:2] # 2次元のndarray
arr[:2, 0] # 1次元のndarray
arr[:, arr[0] > 2] #2次元のndarray
Pandas
なら、
pop = {'Nevada' : {2001 : 2.4, 2002 : 2.9},
'Ohio' : {2000 : 1.5, 2001 : 1.7}}
df = DataFrame(pop) # DataFrame(2次元)
df[df['Nevada'] > 2] # DataFrame(2次元)
df.iloc[-1:]['Nevada'] # Series(1次元)
というような感じで、型は何なん?ってことを意識し理解すれば、半分は終わったようなもんです。
というわけで、ndarray(2次元)のインデックス参照の挙動をまとめてから、Pandas
に進むことにしましょ〜
準備
import
import numpy as np # ndarray
# matplot をjupyterで表示するのに必要
%matplotlib inline
import matplotlib.pyplot as plt
from pandas import Series, DataFrame
import pandas as pd
Numpy
2次元のndarrayを取り上げます。Pandas
を理解するためにここで理解することは、以下の二つです:
-
Numpy
のインデックス参照、スライシング、ブールインデックス参照、ファンシーインデックス参照をきちんと理解している -
2次元の
Numpy
はarr[<行指定>]
,arr[<行指定>, <列指定>]
である(こんがらがらずに理解できている)。
例
arr = np.arange(12).reshape(3,4) # arrは2次元のndarrary(3行4列)
#array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
- indexerの引数が1つだけのときは以下のような感じになります:
# 1次元のndarrayを得る
arr[1] # スカラー値で要素参照
arr[0:2] # スライシング 0行目と1行目を抽出する(2行目は抽出されない)
## 一行目の各要素に対して、(>2)の真偽値を返す
arr[1] > 2 # array([ True, True, True, True], dtype=bool)
# 2次元のndarrayを得る
arr>2 # ブールインデックス参照
arr[np.array([True, False, True])] # ブールインデックス参照で0行目と2行目を抽出する
# arr[[True, False, True]] # Warning
arr[[0,2,1]] # ファンシーインデックス参照 : インデックス参照に(整数)配列を用いる 0行目と2行目と1行目を順序付きで抽出する
-
Numpy
のindexer(2次元ならarr[・(第一引数), ・(第二引数)]
)とします。第一引数が行、第二引数が列にあたります。
基本的には1次元のndarrayと同じなのですが、陥りやすい落とし穴だけメモします:
# 第二引数のみを指定したい時。第一引数は省略できない。その時はスライシング`:`を第一引数としておく
arr[:, 1]
# 第一引数、第二引数にファンシーインデックスを指定すると、ちょっと直感的でない動作をする。
## (1次元のndarrayになってしまうことも注意すること!
## np.array([arr[i,j] for i,j in zip([1,2], [0,1])])と同等。 # array([4, 9])
arr[[1,2], [0,1]]
## 1,2行目かつ0,1列目の領域を抽出するような2次元のndarrayを取得するには、次のようにやる
arr[np.iloc_([1,2], [0,1])]
array([[4, 5],
[8, 9]])
-
Numpy
自体でこういう書き方をする機会は限りなく低いのですが、Pandas
を使用する際に考え方が重要になってくるので、以下に記述しておきます(とりあえず飛ばしてOK):
# 行
arr[:,1] > 2 # array([False, True, True], dtype=bool)
# 1列目が(>2)であるような行を抽出する
arr[arr[:,1] > 2] # arr[np.array([False, True, True])]と同じ。(個人的にはあんまり使ったことない)
# arr[arr[:, 1] > 2, :]と同じ。
arr[1] > 5
arr[:, arr[1] > 5] # array([False, False, True, True], dtype=bool)
#arr[:, np.array([False, False, True, True])] # と同じ
まとめると、ndarray(2次元)のインデックス参照の型の挙動は以下のような感じです4:
第一引数\第二引数|なし|スカラー|スライシング|ブールインデックス|ファンシーインデックス
---|---|---|---|---|---|---|---|---|---|---|---
なし|-|❌|❌|❌|❌|
スカラー|1d|0d|1d|1d|1d|
スライシング|2d|2d|2d|2d|2d|
ブールインデックス|2d|1d|2d|(2d)|(1d)|
ファンシーインデックス|2d|1d|2d|(1d)|(1d)|
- 他には、普通の
list
との挙動の違いは押さえておきたい(微妙に違う)
# 以外と間違えてしまう罠。arrの要素を3倍にしたい
> arr = [0,1,2,3]
> arr*4
[0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
> np.arange(4)*4
[0,4,8,12]
# numpyに変換せずに同様のことを行うならば、内包表記で。
> [i*4 for i in range(4)]
[0,4,8,12]
Pandas入門編
Numpy
では、1次元であろうが2次元であろうが、同じndarrayとして扱えばよかったんですが、Pandas
では、1次元 => Series
, 2次元 => DataFrame
として分かれています。なので、名前は違えど、2次元 <=> 1次元の行き来をするため、DataFrame
とSeries
を切り離すことはできません。
例えば、DataFrame
から単一行/列を指定すれば、1次元であるSeries
を抜き出すことができます。逆にSeries
(1次元)のlist
ordict
をDataFrame
(2次元)のコンストラクタの引数に指定することでDataFrame
を作成することができます。
ということで、変数の次元が1次元なのか2次元なのかを理解することはSeries, DataFrame
と名前が変わっても重要になるわけです。
Seriesについて
Seriesの作成
基本的に、コンストラクタにdict
, list
を突っ込むことが多いです。dict
の場合は、index付きのSeries
になります。
# dictを突っ込む例
dic = {'word' : 470, 'camera' : 78}
Series(dic)
# zipとdictの合わせ技でSeriesを生成することもよくあります:
Series(dict(zip(words, frequency)))
インデックス参照
インデックス参照については、1次元のndarrayの拡張です。違いとしては、index名もインデックスの引数として入れることができる点です。
ser = Series(np.random.randn(5), index = list('ABCDE'))
#A 1.700973
#B 1.061330
#C 0.695804
#D -0.435989
#E -0.332942
#dtype: float64
# スライシング
ser[1] # 1行目、つまり'A'行を抽出 0次元(type = float64型)
ser['A'] # 'A'行を抽出(type = float)
ser[1:3] #1,2行目を抽出 (Series(一次元)
ser[-1:] # 最後の行を抽出
ser[:-1] # 最後の行を除く全ての行を抽出
ser[[1,2]] # 1,2行目を抽出(ファンシーインデックス)
ser[['A', 'B']] # (ファンシー)インデックスを文字列で与えることもできる
ser > 0 # serの型はSeries(1次元)で各要素は真偽値
ser[ser > 0] # ブールインデックス(ser > 0)で要素参照
# Read, Write両方できるので、以下のように、該当するもののみに右辺値を書き込むこともできる.
# 左辺値に条件を持っていくテクニックはDataFrameでもよく使う。
ser[ser > 0] = 0
DataFrameについて
DataFrameの作成
- 2次元のものをコンストラクタの引数に突っ込むわけですけど、外側が
list
ordict
ならば、内側はほとんど何でも構わない(list
でもSeries
でもdict
でもtuple
でも可)
# 外側も内側も dictの場合
pop = {'Nevada' : {2001 : 2.4, 2002 : 2.9},
'Ohio' : {2000 : 1.5, 2001 : 1.7}}
df2 = DataFrame(pop)
# Nevada Ohio
#2000 NaN 1.5
#2001 2.4 1.7
#2002 2.9 NaN
# 外側がdict, 内側がseriesの場合
# df1, df2はDataFrame型 (なので、df1['name'], df2['address']はSeries型です)
## column名は['typeA', 'typeB'], index名は[0,1,2,3]
dfA = DataFrame({'typeA' : df1['name'], 'typeB' : df2['address']})
## index名は[0,1,2,3], column名は['name', 'address'] (attributeのTは転置)
dfB = DataFrame([df1['name'], df2['address']]).T
- builtinの
zip
関数を使って、DataFrame
を作ることもよくあります:
dict(zip([1,2,3], [4,5,6,7])) #{1: 4, 2: 5, 3: 6} => DataFrame化できない
list(zip([1,2,3], [4,5,6,7])) #[(1, 4), (2, 5), (3, 6)] => DataFrame化できる(外側:リスト、内側:タプルなので)
pd.DataFrame(list(zip([1,2,3], [4,5,6,7]))) # => OK!
- 2次元ndarrayを突っ込んでも
DataFrame
の作成が可能です。
df = DataFrame(np.arange(12).reshape(3,4), columns = list('ABCD'))
print(df)
A B C D
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
-
Series
との合わせ技でDataFrame
を作成することも。
DataFrame(Series({'word' : 470, 'camera' : 78}), columns = ['frequency'])
Series
からのDataFrame
作成は、初心者編のデータ追加の節でも詳しく見ていきます。
DataFrameのインデックス参照
Pandas
ではdf[・]
ordf.loc[<行指定>]
or,df.loc[<行指定>, <列指定>]
or df.iloc[<行指定>]
or df.iloc[<行指定>, <列指定>]
ができます。df[・]
は以下のように結構紛らわしい挙動をします。
# よく使う
#dfA[1] # runtime error!! 一列目を整数値で取り出せない
#dfA['typeA'] #'typeA'列をSeries(1次元)として抽出
dfA[['typeB', 'typeA']] # typeB, typeA列を順序込みでDataFrame(2次元)として抽出
dfA['typeA'] > 3 # 1次元のSeries (各要素は真偽値)
# ちょっとややこしい(が個人的にはよく使う)
dfA[dfA['typeA'] > 3] # dfAの'typeA'列が3以上である行を抽出。
# dfA.loc[dfA['typeA'] > 3] #不安なら こちらを使うべし
# 以下、かなりややこしいので、あまり使わない。
dfA[1:] # 1行目~をDataFrame(2次元)として抽出(行の抽出であることに注意)
#dfA[1:]よりも自分ならこう書く。
dfA.loc[1:] # 行指定であることを明示。もしくは、dfA.loc[1:, :]
df.loc
はNumpy
のラベル名指定もOKなバージョンです。ということで、基本的に、Numpy
のインデックス参照と同じノリで書けばよろしい.
df.loc
の注意事項
ただし、df.loc
を扱う際の注意事項としては、2つあります(結構重要かつはまりやすい)。
一つは、df.loc
はラベル名優先なので、index
に整数値が指定されていた時もインデックスの番号が参照されるのではなく、ラベル名に対応する行が抽出される点です。例えばsort
して1番目までの行を抽出したい時とかは、結構事故になりやすいです:
dic = list(zip([0,3,5,6], list('ADCB')))
dfA = DataFrame(dic, columns = ['typeA', 'typeB'])
# typeA typeB
#0 0 A
#1 3 D
#2 5 C
#3 6 B
dfA = dfA.sort_values(by = 'typeB')
# typeA typeB
#0 0 A
#3 6 B
#2 5 C
#1 3 D
dfA.loc[1] #1番目の(つまり2位の)行を抽出したいが、locを用いると、indexのラベル名1の行が抽出される:
#typeA 3
#typeB D
#Name: 1, dtype: object
## こういう悲惨なことを防ぐには、df.ilocを用いる。行番号が優先される。
##(#3 6 B)が抜き出せる
dfA.iloc[1]
iloc
は抽出後にもよく使います.(index
が番号順で無くなっている場合はloc[番号]
で参照できない)
df = df[df['A'] == name]
df.iloc[0]['B'] # ちょっとすっきりしない感じはするが...
もう一つは、これも整数値インデックスを扱う場合に陥りやすい罠ですが、最終行を抜き出したいときは、df.loc
に負の値を要素参照すると失敗します。ラベル名優先なので、-1のラベルなんてないよ〜って言われるわけです。この場合もdf.iloc
を用いて、行番号に関する抽出であることを強調することで解決します。
# dfA.loc[-1] : NG
dfA.iloc[-1] # OK(最終行がSeries(1次元)として抽出される)
dfA.iloc[-1:] # OK(最終行がDataFrame(2次元)として抽出される)
逆にdf.iloc
は番号しか使えないので、行は行番号で、列はラベル名で指定したい時は、以下のように書くと良い。
df.iloc[i]['A'] # こう書くのが良い
# ilocは列指定は数字しかできない
# Location based indexing can only have
# [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array] types
# res *= df.iloc[i, 'A'] #error
DataFrame
のインデックス参照についてまとめると、
-
不安なら、
df[・]
よりもdf.loc[<行指定>]
or,df.loc[<行指定>, <列指定>]
を用いる。 -
ただし、行番号の抽出を強調したい場合は、
df.iloc[<行指定>]
ordf.iloc[<行指定>, <列指定>]
を用いる。
の2点だけ頭に入れとけば、Numpy
のインデックス参照と同じように楽しいデータ抽出ができます。本当はdf.loc
の一種類のみ覚えれば良いなら気楽なんですが、整数値インデックスは実用上非常によく用いられるので、df.iloc
の使用を避けるわけにはいかないのですよ
補足
loc
, iloc
は以下のようにindexerを2重に使うとコピー <= 左辺値に置けない.(もとのDataFrameの修正したい値が修正されない)
#A value is trying to be set on a copy of a slice from a DataFrame
df.loc[5]['colA'] # 左辺値にはできません
# 問題なし! (参照なので)
df.loc[k, 'non_view_rate'] *= mult
Pandas初心者編
ここまではPandas
のインデックス参照について見ていきました。たぶん山場は超えたのですが、DataFrame
の追加とか修正とかそこらへんのややこしい部分が残っております。各関数の基本的な使い方については、 Pythonによるデータ分析入門-―NumPy、pandasを使ったデータ処理 にお任せして、ここでは、逆引き的な感じにまとめていきたい。
Pandasを用いたで〜たの整形方法
追加(連結)
ser = Series([1,2,3], index = list('ABC'))
#A 1
#B 2
#C 3
#dtype: int64
をSeries(3*1)
と表現することにします。index名は全て同じとします。(['A', 'B', 'C']
) いろいろなパターンのデータの連結方法を見ていきます。
(Series(3*1) <- Series(3*1)) -> DataFrame
-
DataFrame(2*3)
にしたい
DataFrame([s1, s2]) #コンストラクタをもちいて
-
DataFrame(3*2)
にしたい
df = DataFrame([s1, s2], index = list('AB')).T
pd.concat([s1, s2], axis = 1) # 下方向に積み上げたいときはconcat(.., axis = 1)を用いれば良い
-
DataFrame(6*1)
にしたい
serA.append(serB)
# または、
pd.concat([serA, serB])
# インデックス名を0の連番にしたければ..
s1.append(s2).reset_index(drop = True) # インデックスを再振り分け
-
DataFrame(1*6)
にしたい
df1 = DataFrame(serA)
df2 = DataFrame(serB)
ndf = df1.join(df2, how = 'outer', lsuffix = 'A', rsuffix = 'B') #かなぁ
# こっちは二つしか連結できないけれど。
ndf = pd.merge(df1, df2, left_index=True, right_index=True, how='outer')
0A 1A 2A 0B 1B 2B
0 1 2 3 4 5 6
(DataFrame(n*3) <- Series(3*1)) => DataFrame
-
DataFrame((n+1)*3)
にしたい
# Can only append a Series if ignore_index=True or if the Series has a index name
df.append(serA, ignore_index = True)
cols = ['colA', 'colB', 'colC']
res_df = DataFrame(columns = cols)
res_df = res_df.append(Series([1,2,3], cols).T, ignore_index = True)
...
複数のSeriesを積み重ねたい
- こんなかんじにしたい
(Series(3*1) + Series(3*1)) + Series(3*1) + Series(3*1)-> DataFrame(4*3)
df = DataFrame([serA, serB, serC, serD])
# DataFrame(3*4)にしたい場合は.Tをつければ良い
df = DataFrame([serA, serB, serC, serD]).T
既存のDataFrameに最終行(Series)を下方向に追加したい(または下方向にDataFrameを追加する)
# 1行追加
df.loc['newrow'] = 0
df.append(serA, ignore_index = True)
# 複数行を追加
df1.append(df2)
# 複数のDataFrameを追加(リストを突っ込める)
df1.append([df2, df3, df4])
# または、
pd.concat([df1, df2, df3, df4])
# 1列追加
df['newcol'] = 0
indexがほぼ共通していて,dfを右方向につなげたい
# 該当しないindexは外部結合(outer)にする。(NAN値にする。)
df1.join(df2, how = 'outer')
df1.join([df2, df3], how = 'outer')
# mergeはもっと細やかなことができるが、2つのDataFrameの結合に限定される:
df1.merge(df1, how = 'outer')
その他の追加
- データベース風のマージ
df1.merge(df2)
とかについては、[1]とかを参考にしてください。
その他くわしきことは、公式ページ http://pandas.pydata.org/pandas-docs/version/0.19.1/generated/pandas.DataFrame.merge.html とか、 http://sinhrks.hatenablog.com/entry/2015/01/28/073327 がいいかな、と思います。
後者については、
+ 縦方向のシンプルな連結 DataFrame.append
+ 柔軟な連結 pd.concat
+ 列の値による結合 pd.merge
+ index による結合 DataFrame.join (mergeのmake easy版)
のようなことが図、例とともに書かれているので、わかりやすいです。
DataFrameの内容を修正する
index, columnsの名前を全部変更したい
# indexの名前変更
df.index = ['one', 'two', 'three']
# indexの番号再振り分け
df.reset_index(drop = True) # インデックスを再振り分け(0番から~)
# columnsの名前変更
## table作成=>編集後はcolumnが想定する並びになっていない可能性があるので、
## 明示的にcolumnの並びを指定した方が無難。
df = df[['old_a', 'old_b', 'old_c']]
df.columns = ['new_a', 'new_b', 'new_c']
# もしくは、df.renameを使う
df = df[['old_a', 'old_b', 'old_c']] #columnの並び順を気にしなければどっちでも。
# renameは破壊的メソッドではないので、左辺値に代入する必要がある。parameterはcolumnsを指定。(axisパラメータではないことに注意)
df = df.rename(columns = {'old_a' : 'new_a', 'old_b' : 'new_b', 'old_c' : 'new_c'})
Note1) 一部のindex, column名を変更したいときにもdf.rename
が使える。(index
かcolumns
パラメータにdict
型(変更前-変更後の対応表として)を指定する。axis
パラメータはないので、注意すること。あとは、column
でなくcolumns
(s
をつける))
Note2) reindex
は既存のindexの位置の入れ替えであって、index名の変更ではない。
set_indexはdf.set_index(['c1','c0'])
というように、特定の1つ以上の列をインデックスとして使用した新しいオブジェクトを作成する。indexの名前の変更するメソッドではないことに注意。reset_index
は階層型インデックスが列に変換される。ちょうどset_index <=> reset_index
の関係。
代入
- ある列内で所要の条件に当てはまった行の別の列を変更する
# 'A'列に着目して、'wrong'である行を選択し、それらの行の'B'列を'sth'に変更する
df.loc[df['A'] == 'wrong', 'B'] = 'sth'
-
sort_index
(indexを軸にしたソートの場合),sort_values
(特定の列(by
で指定)で昇順,降順にsortできる(降順のばあいは,ascending = False
を指定)
抽出
-
df[・]
に複数のブールインデックスを入れたいばあい。
# それぞれのブールインデックスはカッコで囲むこと
df = df[(df['A'] > 0) | (df['B'] > 0)]
-
df[・]
の要素それぞれについて複数の候補内にあるかを調べたい場合
# applyはSeriesを引数にとる関数(ラムダ式)を第一引数に突っ込む
# mapは要素を引数にとる関数(ラムダ式)を第一引数に突っ込む
df = df[df['A'].map(lambda d : d in listA)]
削除
行、列の削除はdf.drop
で(non-destractive)。axisを指定すれば、行でも列でも削除可能
df = df.drop("A", axis=1)
# columnが'A', 'B', .. 'F'で'C'列から'F'列まで削除したいときとかは、以下のようにする方が多い
df = df[['A', 'B']]
naを取り除く
http://nekoyukimmm.hatenablog.com/entry/2015/02/25/222414 を参照。
- NANの含まれている部分の行や列を丸ごと削除したい時は
how = 'all'
を指定すればOKです。
ブールインデックス参照
- ブール型の取得方法
# DataFrame型を返す
df.apply(lambda ser: ser % 2 == 0)
df.applymap(lambda x: x % 2 == 0)
df['goal'] == 0
df.isin([1,2])
df = df[~df.index.duplicated()] # indexの重複の削除(2回目以降に出てくるデータを削除)
# Series型を返す
df.apply(lambda ser : (ser > 0).any())
df['A'].map(lambda x : x > -1)
serA > serB # series型
-bool_ser # boolインデックスの要素のインデックスをひっくり返す
# 第二引数は第一引数でFalseになる要素のみ
df['A'].where(df['A'] > 0, -df['A']) # absのSeries版(第一引数に当てはまらなければ、負の符号をつける(つまり、負に負をかけるので、正になる)
(df['goal'] == 0).all() # 条件に全てあてハマっていれば、True
df.apply(lambda ser: ser % 2 == 0)
(df['cdf(%)'] < 90).sum() # 条件に当てはまる個数をカウント
df.where(df % 3 == 0, -df)
NA値が割り当てられる可能性のある書き方
結構、NA
周りではまることも多いので、どこで NA
値を発生させる可能性があるのかをメモ。
- コンストラクタのindex, columns
dic = dict(zip(list('ABCD'), [3,4,6,2])) # dictを生成
ser = Series(dic, index = list('ABCDE'))
# dicにないE列がNANになっている
#A 3.0
#B 4.0
#C 6.0
#D 2.0
#E NaN
#dtype: float64
- DataFrameコンストラクタのdataパラメタに辞書に乗っていない
(例)
pop = {'Nevada' : {2001 : 2.4, 2002 : 2.9},
'Ohio' : {2000 : 1.5, 2001 : 1.7}}
df = DataFrame(pop)
Nevada Ohio
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 NaN
-
df.reindex
でindexパラメータにdfのindexに含まれないものが入っている場合。
例は省略
-
loc
フィールドを用いたインデックス参照
df.loc[[2002, 2001, 1999], ['Alaska', 'Nevada']]
Alaska Nevada
2002 NaN 2.9
2001 NaN 2.4
1999 NaN NaN
Note) df['non_exists']
, df.loc[:, 'non_exists']
(columnに無い名前を指定してしまう)とエラー。
-
データフレーム同士の加算(
index
orcolumn
の対応しない要素がNANになる) -
merge, join
にhow='outer'
とかを指定した場合 -
append, concat
(indexが対応していない場合)
NA値を取り除く方法
-
df.dropna
(parameterはhowとかaxisとか),df.fillna(0)
(NA値を一律0にする -
df.reindex
にfill_value
パラメータまたはmethod
パラメータを指定 -
combine_first
:old_df
のNA値のみが第一引数によって補完される。(old_dfで要素が0になっている箇所はパッチあての対象とならないので、注意!)
# df .. indexが飛び飛び(index.name : B_idx, columns = ['A'] => indexを連番(0~89)として、補間値を0としたい
old_df = DataFrame(index = range(90), columns = 'A')
new_df = old_df.combine_first(df).fillna(0) # index.nameは消える
文字列の操作
特にSeries
の文字列操作は地味によく使うので。要素だけでなく、index名、column名に対しても、使えます!
詳しくは、 http://pandas.pydata.org/pandas-docs/stable/text.html (特に最下部)をみてください。DataFrame内で文字列操作をしたい時は、だいたいここみれば解決します。
使い所としては、例えば、ある正規表現にマッチする行だけを抜き出したい場合とか。
# dfの'A'列の中で先頭が英小文字に当たる行のみを抽出して、dfを更新する
r = '^[a-z]'
df = df[df['A'].str.match(r)] # df['A'].str.match(r)はブールインデックス
参考文献
[1] Pythonによるデータ分析入門-―NumPy、pandasを使ったデータ処理
[2] http://sinhrks.hatenablog.com/entry/2015/01/28/073327
[3] Documentation http://pandas.pydata.org/pandas-docs/stable/api.html