Pandas 集中講座 その2 選択
Pandasライブラリを覚えたい!公式「10 Minutes to pandas」をモチーフに使って実際に動作させ学習する。第2回 選択
Pandas 集中講座(2)
Pandas 集中講座 その1 - chiyoh’s blog
Pandas 集中講座 その2 - chiyoh’s blog
Pandas 集中講座 その3 - chiyoh’s blog
Pandas 集中講座 その4 - chiyoh’s blog
Pandas 集中講座 その5 - chiyoh’s blog
Pandas 集中講座 その6 - chiyoh’s blog
Pandasとは、なにか?
初め考えていたのは、EXCELシートも扱えるPython版スプレッドシートライブラリ。 VBAの代わりにマクロをPython上で実行できる便利なものと考えていた。
Pandasを実際に使ってみると
始めて使ったのは、テキストデータをEXCELのxlsxに変換しておきたかったから。実際に変換してみると思ったより難しい(実際には、我々がEXCELを表計算としてとらえていなくて計算機能と印刷機能を持つワープロとして使っているのが原因)。また、Pandasも高機能なので出来ることが多く大いに迷ったが、それでもEXCELファイルの書き出しに成功したのでこれは便利だ!ということでこれを機に少し使ってみようと考えた。
公式「10 Minutes to pandas」を実際にやってみる (2/6)
Pandasを覚える!さて、グーグル先生に教えてもらえば大抵のことは分かるのだが、それが今の最適解なのか?と考えるとそうではない。グーグル先生のサーチ機能は、カンニングペーパーであり、単語帳である。欲しい答えを最小ステップでたどり着くための方法。例えるなら、望遠鏡、又は顕微鏡で拡大されたエリアで見つけた希望(答え)。なぜそうなるのか?なぜそう書けば動くのか?など、答えに対する成り立ちがすっぽり抜けてしまうのである。最近のPython環境は、Jupyter Notebookで敷地も下がって来ている。入門書や学習本を眺めて図を見てなんとなくへーとか言って分かった気になって何も残らないパターンになりかねない。今回選んだ方法は、グーグル先生の支援のもと公式のチュートリアル以前のPandas概要説明『10 Minutes to pandas』を上から順にJupyter Notebookを使い実行していってみようと思う。これにより、学習講座のWorkshop形式で講師が腹痛で欠席したので自己学習してなさい版くらいの知識に残ることを期待。実行した結果をここに残し、その時のメモ書きとエッセンスと晒してみる。
【解説】公式「10 Minutes to pandas」をJupyter Notebookを使って動作させながら確認し、突っ込みを入れる!(この文章を見る価値としては、原書が何をやっているのかが分かる、、、分かるはずである)
公式「10 Minutes to pandas」を実際にやってみる
3.選択(Selection)
注意:選択と設定のための標準的なPython / Numpy式は直感的でインタラクティブな作業には便利ですが、プロダクションコードのためには、最適化されたpandasデータアクセスメソッド、.at、.iat、.locおよび.ilocをお勧めします。
インデックス作成のドキュメントインデックス作成とデータの選択およびMultiIndex / Advanced Indexingを参照してください。
【解説】Pandasで最適化されたアクセス方法を用意してあるのでそっちを使ってね。ということか、Python / Numpy式が何かは分かりにくいが今私たちが思い浮かぶアクセスだよね?付けて選択する方法とかでx,y座標的につかったりするやりかた。[::-1]とかもかな
配列形式な選択 ()
単一の列を選択すると、単一Seriesオブジェクトとなりdf.Aでもあります。
df['A']
2019-05-01 -0.149943
2019-05-02 0.108830
2019-05-03 -0.627742
2019-05-04 -0.000103
2019-05-05 -0.064446
2019-05-06 -0.438960
Freq: D, Name: A, dtype: float64
df.A
2019-05-01 -0.149943
2019-05-02 0.108830
2019-05-03 -0.627742
2019-05-04 -0.000103
2019-05-05 -0.064446
2019-05-06 -0.438960
Freq: D, Name: A, dtype: float64
type(df['A'])
pandas.core.series.Series
【実況】Numpy形式か?
間を選択すると行がスライスされます。
df[0:3]
A | B | C | D | |
---|---|---|---|---|
2019-05-01 | -0.149943 | 0.785767 | 0.622169 | 1.553862 |
2019-05-02 | 0.108830 | 1.195339 | 1.791636 | 1.337328 |
2019-05-03 | -0.627742 | -0.601345 | 0.201793 | -0.685570 |
df['20190502':'20190504']
A | B | C | D | |
---|---|---|---|---|
2019-05-02 | 0.108830 | 1.195339 | 1.791636 | 1.337328 |
2019-05-03 | -0.627742 | -0.601345 | 0.201793 | -0.685570 |
2019-05-04 | -0.000103 | -0.482461 | -1.541615 | -0.710261 |
【解説】column列を選択するのには、[column名]でよく、index行選択には[index行:index行]でする
a=[0,1,2,3,4,5] a[0:2]
[0, 1]
【解説】だよね?Numpyと少し動作が違うNumpyでは[start:end:step]がイタレーション的forループで作られているから条件式部分がcount<endで定義されているのでendは含まれない。[start:end:step]分かりにくい元か[init:times:step]が適切init初期値、times何回ループするか、stepループ時の増減値なのでPandasの直感的なここからここまでな[from:to]みたいなとは別になる
【余談】なんで別にした?と思ったがindexが数値で連続性を持っているとは限らないので次のデータが+1で指定できないためか
df['20190503']
KeyError: '20190503'
【解説】DatetimeIndexなんて特別なクラスを使っているから'2019-05-03'を'20190503'と省略して書けるのね。それは置いておいて、1つ選ぶのに直接呼び出したらエラーになった。これはスライスして同じ値を入れることで回避できる
df['2019-05-03':'2019-05-03']
A | B | C | D | |
---|---|---|---|---|
2019-05-03 | -0.627742 | -0.601345 | 0.201793 | -0.68557 |
ラベルによる選択(.loc[]) 行選択
ラベルによる選択の詳細を参照してください。ラベルを使って断面を取得するには:
df.loc[dates[0]]
A -0.149943
B 0.785767
C 0.622169
D 1.553862
Name: 2019-05-01 00:00:00, dtype: float64
【実況】dates[0]ってなんだ?dfを定義したときに使った変数だけど。10分講座だから覚えているよね?むりー
dates = pd.date_range('20190501', periods=6) df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD')) df
A | B | C | D | |
---|---|---|---|---|
2019-05-01 | 0.451080 | 1.378920 | -0.897954 | 0.382555 |
2019-05-02 | -0.250102 | -1.663388 | 0.010251 | -1.531969 |
2019-05-03 | -1.061661 | 0.248446 | -1.246751 | 1.907569 |
2019-05-04 | 0.064499 | 0.386742 | -0.841549 | -1.483970 |
2019-05-05 | -0.694038 | -0.496932 | 0.070118 | -0.056977 |
2019-05-06 | -0.422955 | 0.824024 | 0.654380 | 0.202406 |
df.loc[dates[0]]
A 0.451080
B 1.378920
C -0.897954
D 0.382555
Name: 2019-05-01 00:00:00, dtype: float64
dates
DatetimeIndex(['2019-05-01', '2019-05-02', '2019-05-03', '2019-05-04',
'2019-05-05', '2019-05-06'],
dtype='datetime64[ns]', freq='D')
dates[0]
Timestamp('2019-05-01 00:00:00', freq='D')
【解説】indexに使ったDatetimeIndex形式はインスタンス化するときに'20190501'として日まで入力しているが実際は秒まで認識している。EXCELでいうところのシリアル値(int64)で内部処理されている
df.loc[dates[-1]]
A -0.422955
B 0.824024
C 0.654380
D 0.202406
Name: 2019-05-06 00:00:00, dtype: float64
df.loc['2019-05-03']
A -1.061661
B 0.248446
C -1.246751
D 1.907569
Name: 2019-05-03 00:00:00, dtype: float64
【解説】[]では、ダメでしたが.loc[]では、OKのようです
df.loc[:]
A | B | C | D | |
---|---|---|---|---|
2019-05-01 | 0.451080 | 1.378920 | -0.897954 | 0.382555 |
2019-05-02 | -0.250102 | -1.663388 | 0.010251 | -1.531969 |
2019-05-03 | -1.061661 | 0.248446 | -1.246751 | 1.907569 |
2019-05-04 | 0.064499 | 0.386742 | -0.841549 | -1.483970 |
2019-05-05 | -0.694038 | -0.496932 | 0.070118 | -0.056977 |
2019-05-06 | -0.422955 | 0.824024 | 0.654380 | 0.202406 |
【解説】[:]は、index全部
ラベルで多軸を選択: 行と列選択 (.loc[ix,col] ラベルで行と列のグループにアクセス)
df.loc[:, ['A', 'B']]
A | B | |
---|---|---|
2019-05-01 | 0.451080 | 1.378920 |
2019-05-02 | -0.250102 | -1.663388 |
2019-05-03 | -1.061661 | 0.248446 |
2019-05-04 | 0.064499 | 0.386742 |
2019-05-05 | -0.694038 | -0.496932 |
2019-05-06 | -0.422955 | 0.824024 |
【実況】分かりにくいdf.loc[row_indexer] または、df.loc[row_indexer,column_indexer]なのか?
df.loc[:, ['A', 'C']]
A | C | |
---|---|---|
2019-05-01 | 0.451080 | -0.897954 |
2019-05-02 | -0.250102 | 0.010251 |
2019-05-03 | -1.061661 | -1.246751 |
2019-05-04 | 0.064499 | -0.841549 |
2019-05-05 | -0.694038 | 0.070118 |
2019-05-06 | -0.422955 | 0.654380 |
【解説】リスト形式にすることで、columnを複数選択できる。スライスとは違う
ラベルスライスを表示すると、両方のエンドポイントが含まれます。
df.loc['20190502':'20190504', ['A', 'B']]
A | B | |
---|---|---|
2019-05-02 | -0.250102 | -1.663388 |
2019-05-03 | -1.061661 | 0.248446 |
2019-05-04 | 0.064499 | 0.386742 |
df.loc[:, 'A':'B']
A | B | |
---|---|---|
2019-05-01 | 0.451080 | 1.378920 |
2019-05-02 | -0.250102 | -1.663388 |
2019-05-03 | -1.061661 | 0.248446 |
2019-05-04 | 0.064499 | 0.386742 |
2019-05-05 | -0.694038 | -0.496932 |
2019-05-06 | -0.422955 | 0.824024 |
【解説】indexだけでなくcolumnもスライスできます
返されるオブジェクトのサイズを縮小します。
df.loc['20190502', ['A', 'B']]
A -0.250102
B -1.663388
Name: 2019-05-02 00:00:00, dtype: float64
type(df.loc['20190502', ['A', 'B']])
pandas.core.series.Series
【解説】indexが、一つの場合column列のSeriesを返してくる。
スカラー値を取得するには
df.loc[dates[0], 'A']
0.45107999031214707
type(df.loc[dates[0], 'A'])
numpy.float64
【解説】Index行とcolumn列を1ずつ選択するとスカラー値で戻ってくる
df.loc['20190502', ['A']]
A -0.250102
Name: 2019-05-02 00:00:00, dtype: float64
type(df.loc['20190502', ['A']])
pandas.core.series.Series
df.loc['20190502', ['A']][0]
-0.25010196341642593
【解説】1ずつ選択だが、 ['A']が複数選択形式、indexが1つなのでSeriesで戻してくる
df.loc['20190502':, ['A']]
A | |
---|---|
2019-05-02 | -0.250102 |
2019-05-03 | -1.061661 |
2019-05-04 | 0.064499 |
2019-05-05 | -0.694038 |
2019-05-06 | -0.422955 |
【解説】複数指定方式同士にするとDataFrameになる
スカラーへの高速アクセスを得るために(前のメソッドと同等): (.at 単一アクセス)
df.at[dates[0], 'A']
0.45107999031214707
位置による選択 (.iloc[])
位置による選択の詳細を参照してください。渡された整数の位置で選択します。
a = np.array(range(100)).reshape(10,10).T[:6,:4] df = pd.DataFrame(a, columns=list('ABCD')) df
A | B | C | D | |
---|---|---|---|---|
0 | 0 | 10 | 20 | 30 |
1 | 1 | 11 | 21 | 31 |
2 | 2 | 12 | 22 | 32 |
3 | 3 | 13 | 23 | 33 |
4 | 4 | 14 | 24 | 34 |
5 | 5 | 15 | 25 | 35 |
【解説】表が分かりにくいので、行が1の位、列が10の位が変化する表に差し替えた
df.iloc[3]
A 3
B 13
C 23
D 33
Name: 3, dtype: int32
【解説】[ ]指定なので配列風,行列風な指定方法です。[index]でカラムに対するデータを選択します
整数スライスで、numpy / pythonに似た動作をします。
df.iloc[3:5, 0:2]
A | B | |
---|---|---|
3 | 3 | 13 |
4 | 4 | 14 |
【解説】こっちが、Numpyと同じスライスの終わりが含まれないという動作ですね
整数位置のリストで、numpy / pythonスタイルに似ています。
df.iloc[[1, 2, 4], [0, 2]]
A | C | |
---|---|---|
1 | 1 | 21 |
2 | 2 | 22 |
4 | 4 | 24 |
【実況】え?そうなん?
【解説】内容に付いて、indexの1, 2, 4を選択 colの0列目と2列目を選択交差した部分を選択
list_a = [[ 0, 10, 20, 30],[ 1, 11, 21, 31], [ 2, 12, 22, 32],[ 3, 13, 23, 33], [ 4, 14, 24, 34],[ 5, 15, 25, 35]] list_a
[[0, 10, 20, 30],
[1, 11, 21, 31],
[2, 12, 22, 32],
[3, 13, 23, 33],
[4, 14, 24, 34],
[5, 15, 25, 35]]
list_a[[1, 2, 4], [0, 2]]
TypeError: list indices must be integers or slices, not tuple
a[[1, 2, 4], [0, 2]]
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,)
【解説】どの辺がnumpy/python風なのか分かりません
行を明示的にスライスする場合:
df.iloc[1:3, :]
A | B | C | D | |
---|---|---|---|---|
1 | 1 | 11 | 21 | 31 |
2 | 2 | 12 | 22 | 32 |
列を明示的にスライスする場合
df.iloc[:, 1:3]
B | C | |
---|---|---|
0 | 10 | 20 |
1 | 11 | 21 |
2 | 12 | 22 |
3 | 13 | 23 |
4 | 14 | 24 |
5 | 15 | 25 |
【解説】:(スライス)のみで全体選択をして、もう片方をIndexかcolumnを選ぶやり方ですね
明示的に値を取得するには
df.iloc[1, 1]
11
【解説】Indexとcolumnを1つに限定するとスカラー値として取り出せる
スカラーへの高速アクセスを得るために(前のメソッドと同等):
df.iat[1, 1]
11
【解説】loc[]と同様にat[]の代わりにiat[]が単一選択の高速版になります
ブール索引付け
単一列の値を使用してデータを選択する
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD')) df
A | B | C | D | |
---|---|---|---|---|
2019-05-01 | -0.106726 | -1.762983 | -1.265036 | -0.404320 |
2019-05-02 | -0.690402 | -0.045117 | -0.684309 | 1.756284 |
2019-05-03 | -0.479369 | 0.419347 | 1.396591 | -0.762011 |
2019-05-04 | 0.497103 | 0.760560 | -2.488575 | -0.670358 |
2019-05-05 | 0.974668 | -1.191495 | -1.674198 | 1.348520 |
2019-05-06 | -1.740956 | 0.539032 | 0.709385 | -1.034903 |
df[df.A > 0]
A | B | C | D | |
---|---|---|---|---|
2019-05-04 | 0.497103 | 0.760560 | -2.488575 | -0.670358 |
2019-05-05 | 0.974668 | -1.191495 | -1.674198 | 1.348520 |
【解説】A列で0より大きいindex行を選択しなさい
df.A
2019-05-01 -0.106726
2019-05-02 -0.690402
2019-05-03 -0.479369
2019-05-04 0.497103
2019-05-05 0.974668
2019-05-06 -1.740956
Freq: D, Name: A, dtype: float64
df.A > 0
2019-05-01 False
2019-05-02 False
2019-05-03 False
2019-05-04 True
2019-05-05 True
2019-05-06 False
Freq: D, Name: A, dtype: bool
【解説】内容的には、df.A
(df['A'])でA列を選択 df.A >0
A列の中で0以上のものをTrueとして判定。df[ index ]なので、dfのindexの並び順に照らし合わせてTrueの行のみを選択した
ブール条件が満たされるDataFrameから値を選択する。
df[df > 0]
A | B | C | D | |
---|---|---|---|---|
2019-05-01 | NaN | NaN | NaN | NaN |
2019-05-02 | NaN | NaN | NaN | 1.756284 |
2019-05-03 | NaN | 0.419347 | 1.396591 | NaN |
2019-05-04 | 0.497103 | 0.760560 | NaN | NaN |
2019-05-05 | 0.974668 | NaN | NaN | 1.348520 |
2019-05-06 | NaN | 0.539032 | 0.709385 | NaN |
df > 0
A | B | C | D | |
---|---|---|---|---|
2019-05-01 | False | False | False | False |
2019-05-02 | False | False | False | True |
2019-05-03 | False | True | True | False |
2019-05-04 | True | True | False | False |
2019-05-05 | True | False | False | True |
2019-05-06 | False | True | True | False |
【解説】さらに分かりにくいdf>0なので全体に足して0より大きいがどうかを判定している。これはいい。それをdf[ index,colum ]で全体適応したのでTrueのところは選択されて数値をFlaseのところはMaskされてnp.NaN表記になったという感じか?
df.loc[pd.Timestamp(2019, 5, 7, 0)] = -10 df.loc["2019-05-08"] = -10 df['E'] = -10 df
A | B | C | D | E | |
---|---|---|---|---|---|
2019-05-01 00:00:00 | -0.106726 | -1.762983 | -1.265036 | -0.404320 | -10 |
2019-05-02 00:00:00 | -0.690402 | -0.045117 | -0.684309 | 1.756284 | -10 |
2019-05-03 00:00:00 | -0.479369 | 0.419347 | 1.396591 | -0.762011 | -10 |
2019-05-04 00:00:00 | 0.497103 | 0.760560 | -2.488575 | -0.670358 | -10 |
2019-05-05 00:00:00 | 0.974668 | -1.191495 | -1.674198 | 1.348520 | -10 |
2019-05-06 00:00:00 | -1.740956 | 0.539032 | 0.709385 | -1.034903 | -10 |
2019-05-07 00:00:00 | -10.000000 | -10.000000 | -10.000000 | -10.000000 | -10 |
2019-05-08 | -10.000000 | -10.000000 | -10.000000 | -10.000000 | -10 |
【解説】"2019-05-08"だけでは、strのindexが挟み込まれたとして識別されてしまうみたいだ
df[df > 0]
A | B | C | D | E | |
---|---|---|---|---|---|
2019-05-01 00:00:00 | NaN | NaN | NaN | NaN | NaN |
2019-05-02 00:00:00 | NaN | NaN | NaN | 1.756284 | NaN |
2019-05-03 00:00:00 | NaN | 0.419347 | 1.396591 | NaN | NaN |
2019-05-04 00:00:00 | 0.497103 | 0.760560 | NaN | NaN | NaN |
2019-05-05 00:00:00 | 0.974668 | NaN | NaN | 1.348520 | NaN |
2019-05-06 00:00:00 | NaN | 0.539032 | 0.709385 | NaN | NaN |
2019-05-07 00:00:00 | NaN | NaN | NaN | NaN | NaN |
2019-05-08 | NaN | NaN | NaN | NaN | NaN |
【解説】df[df > 0]
適応するときA列から順に適応して結果をSeriesにしてそれを総合してindexとcolumを決めているのではなく単純に全体を判断して表示しているだけっぽい(indexとE列が削除されてない)
isin()フィルタリング方法を使用する:
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD')) df
A | B | C | D | |
---|---|---|---|---|
2019-05-01 | 1.111420 | -0.179004 | 1.799883 | 0.569833 |
2019-05-02 | 1.040001 | -0.743061 | 0.310026 | 0.121585 |
2019-05-03 | -0.987081 | -1.032944 | -0.367010 | -1.180204 |
2019-05-04 | 0.164185 | -0.573081 | -0.544974 | 0.859824 |
2019-05-05 | 0.769549 | 3.183677 | -0.426652 | 0.700605 |
2019-05-06 | -1.005111 | 0.095534 | -0.842821 | 1.181250 |
df2 = df.copy() df2['E'] = ['one', 'one', 'two', 'three', 'four', 'three'] df2
A | B | C | D | E | |
---|---|---|---|---|---|
2019-05-01 | 1.111420 | -0.179004 | 1.799883 | 0.569833 | one |
2019-05-02 | 1.040001 | -0.743061 | 0.310026 | 0.121585 | one |
2019-05-03 | -0.987081 | -1.032944 | -0.367010 | -1.180204 | two |
2019-05-04 | 0.164185 | -0.573081 | -0.544974 | 0.859824 | three |
2019-05-05 | 0.769549 | 3.183677 | -0.426652 | 0.700605 | four |
2019-05-06 | -1.005111 | 0.095534 | -0.842821 | 1.181250 | three |
df2[df2['E'].isin(['two', 'four'])]
A | B | C | D | E | |
---|---|---|---|---|---|
2019-05-03 | -0.987081 | -1.032944 | -0.367010 | -1.180204 | two |
2019-05-05 | 0.769549 | 3.183677 | -0.426652 | 0.700605 | four |
df2['E'].isin(['two', 'four'])
2019-05-01 False
2019-05-02 False
2019-05-03 True
2019-05-04 False
2019-05-05 True
2019-05-06 False
Freq: D, Name: E, dtype: bool
df2['E']
2019-05-01 one
2019-05-02 one
2019-05-03 two
2019-05-04 three
2019-05-05 four
2019-05-06 three
Freq: D, Name: E, dtype: object
type(df2['E'])
pandas.core.series.Series
【解説】E列を使ってフィルタする。df2['E'].isin(['two', 'four'])
は、E列に対してisinを適応isinは、中にある?の関数なので'two'と'four'があるindexのみTrueして判定1列なのでSeriesが戻ってくる。それをdf2[ ]全体に適応するとTrueの行のみが選択される。
df2[df2.isin(['two', 'four'])]
A | B | C | D | E | |
---|---|---|---|---|---|
2019-05-01 | NaN | NaN | NaN | NaN | NaN |
2019-05-02 | NaN | NaN | NaN | NaN | NaN |
2019-05-03 | NaN | NaN | NaN | NaN | two |
2019-05-04 | NaN | NaN | NaN | NaN | NaN |
2019-05-05 | NaN | NaN | NaN | NaN | four |
2019-05-06 | NaN | NaN | NaN | NaN | NaN |
df2[df2.isin(['two', 'four'])].fillna(value='')
A | B | C | D | E | |
---|---|---|---|---|---|
2019-05-01 | |||||
2019-05-02 | |||||
2019-05-03 | two | ||||
2019-05-04 | |||||
2019-05-05 | four | ||||
2019-05-06 |
【解説】全体適応させるとこんな感じ
設定 (追加,更新)
新しい列を設定すると、インデックスによってデータが自動的に整列されます。(追加)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD')) df
A | B | C | D | |
---|---|---|---|---|
2019-05-01 | 1.498666 | -0.143574 | -0.871839 | -0.106927 |
2019-05-02 | -0.092376 | 0.036220 | -0.146521 | 0.991350 |
2019-05-03 | -0.307696 | -0.051588 | -0.413379 | 0.826141 |
2019-05-04 | 0.397105 | 1.731472 | -1.033554 | -0.311225 |
2019-05-05 | 1.376085 | 0.310974 | 0.350129 | 0.221216 |
2019-05-06 | 0.821727 | 0.389651 | -1.202223 | -0.354074 |
s1 = pd.Series([1, 2, 3, 4, 5, 6], index=pd.date_range('20190501', periods=6)) s1
2019-05-01 1
2019-05-02 2
2019-05-03 3
2019-05-04 4
2019-05-05 5
2019-05-06 6
Freq: D, dtype: int64
df['F'] = s1
df
A | B | C | D | F | |
---|---|---|---|---|---|
2019-05-01 | 1.498666 | -0.143574 | -0.871839 | -0.106927 | 1 |
2019-05-02 | -0.092376 | 0.036220 | -0.146521 | 0.991350 | 2 |
2019-05-03 | -0.307696 | -0.051588 | -0.413379 | 0.826141 | 3 |
2019-05-04 | 0.397105 | 1.731472 | -1.033554 | -0.311225 | 4 |
2019-05-05 | 1.376085 | 0.310974 | 0.350129 | 0.221216 | 5 |
2019-05-06 | 0.821727 | 0.389651 | -1.202223 | -0.354074 | 6 |
【解説】F列にSeriesデータを代入。結果としてF列が無いので新規に追加してSeriesのデータを各indexに代入された。
s2 = pd.Series([1, 2, 3], index=pd.date_range('20190501', periods=3)) df['G'] = s2 df
A | B | C | D | F | G | |
---|---|---|---|---|---|---|
2019-05-01 | 1.498666 | -0.143574 | -0.871839 | -0.106927 | 1 | 1.0 |
2019-05-02 | -0.092376 | 0.036220 | -0.146521 | 0.991350 | 2 | 2.0 |
2019-05-03 | -0.307696 | -0.051588 | -0.413379 | 0.826141 | 3 | 3.0 |
2019-05-04 | 0.397105 | 1.731472 | -1.033554 | -0.311225 | 4 | NaN |
2019-05-05 | 1.376085 | 0.310974 | 0.350129 | 0.221216 | 5 | NaN |
2019-05-06 | 0.821727 | 0.389651 | -1.202223 | -0.354074 | 6 | NaN |
【解説】インデックスによってデータが自動的に整列されます。の部分が分からなかったけど、追加するデータがindexに足して少ないとその要素はNaNとして扱われる。Gを適応させていくときに自動調整でNaNを追加していくという意味なんでしょう
len(df.index)
6
【解説】lenメソッドでindexの長さが分かるのでデータその分のデータがあるか確認できます
ラベルによる値の設定 (更新)
df.at[dates[0], 'A'] = 0 df
A | B | C | D | F | G | |
---|---|---|---|---|---|---|
2019-05-01 | 0.000000 | -0.143574 | -0.871839 | -0.106927 | 1 | 1.0 |
2019-05-02 | -0.092376 | 0.036220 | -0.146521 | 0.991350 | 2 | 2.0 |
2019-05-03 | -0.307696 | -0.051588 | -0.413379 | 0.826141 | 3 | 3.0 |
2019-05-04 | 0.397105 | 1.731472 | -1.033554 | -0.311225 | 4 | NaN |
2019-05-05 | 1.376085 | 0.310974 | 0.350129 | 0.221216 | 5 | NaN |
2019-05-06 | 0.821727 | 0.389651 | -1.202223 | -0.354074 | 6 | NaN |
dates
DatetimeIndex(['2019-05-01', '2019-05-02', '2019-05-03', '2019-05-04',
'2019-05-05', '2019-05-06'],
dtype='datetime64[ns]', freq='D')
【解説】A列,dates[0]='2019-05-01'行のデータが0.0に更新されました。A列のdtypeがfloat64なので0.0になる
位置による設定値: (更新)
df.iat[0, 1] = 0 df
A | B | C | D | F | G | |
---|---|---|---|---|---|---|
2019-05-01 | 0.000000 | 0.000000 | -0.871839 | -0.106927 | 1 | 1.0 |
2019-05-02 | -0.092376 | 0.036220 | -0.146521 | 0.991350 | 2 | 2.0 |
2019-05-03 | -0.307696 | -0.051588 | -0.413379 | 0.826141 | 3 | 3.0 |
2019-05-04 | 0.397105 | 1.731472 | -1.033554 | -0.311225 | 4 | NaN |
2019-05-05 | 1.376085 | 0.310974 | 0.350129 | 0.221216 | 5 | NaN |
2019-05-06 | 0.821727 | 0.389651 | -1.202223 | -0.354074 | 6 | NaN |
【解説】こっちはかんたんですね。.iat[]なので数値指定できます。
NumPy配列で代入して設定する:
df.loc[:, 'D'] = np.array([5] * len(df)) df
A | B | C | D | F | G | |
---|---|---|---|---|---|---|
2019-05-01 | 0.000000 | 0.000000 | -0.871839 | 5 | 1 | 1.0 |
2019-05-02 | -0.092376 | 0.036220 | -0.146521 | 5 | 2 | 2.0 |
2019-05-03 | -0.307696 | -0.051588 | -0.413379 | 5 | 3 | 3.0 |
2019-05-04 | 0.397105 | 1.731472 | -1.033554 | 5 | 4 | NaN |
2019-05-05 | 1.376085 | 0.310974 | 0.350129 | 5 | 5 | NaN |
2019-05-06 | 0.821727 | 0.389651 | -1.202223 | 5 | 6 | NaN |
len(df)
6
【解説】ラベル(.loc)で追加、Numpyの1次元配列をindex分作って代入しています。
【実況】あれ、そうですかdfにlen()を適応するとindexの行数が戻ってくるんですね。Numpyの場合、要素数になるのでそうかともってました
where設定ありの操作。
df2 = df.copy()
df2[df2 > 0] = -df2
df2
A | B | C | D | F | G | |
---|---|---|---|---|---|---|
2019-05-01 | 0.000000 | 0.000000 | -0.871839 | -5 | -1 | -1.0 |
2019-05-02 | -0.092376 | -0.036220 | -0.146521 | -5 | -2 | -2.0 |
2019-05-03 | -0.307696 | -0.051588 | -0.413379 | -5 | -3 | -3.0 |
2019-05-04 | -0.397105 | -1.731472 | -1.033554 | -5 | -4 | NaN |
2019-05-05 | -1.376085 | -0.310974 | -0.350129 | -5 | -5 | NaN |
2019-05-06 | -0.821727 | -0.389651 | -1.202223 | -5 | -6 | NaN |
【解説】フィルタの全体適応ですね。df2[df2 > 0] = -df2
は、自分に上書きしているのでその点は気を付けましょう。df2>0で0以上を調べTrue/FalseのMaskを作って該当す要素の書き換えをしています。結果としてすべてマイナス要素に代わってます。(0とNaN以外だね)