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形式で講師が腹痛で欠席したので自己学習してなさい版くらいの知識に残ることを期待。実行した結果をここに残し、その時のメモ書きとエッセンスと晒してみる。

pandas.pydata.org

【解説】公式「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以外だね)

chiyoh.hatenablog.com
chiyoh.hatenablog.com