1. Python Pandas もくもく勉強会 in 新潟 #3
2019/08/21 に「Python Pandas もくもく勉強会 in 新潟 #3」を開催しました。本記事は、その時に行われた質問やアドバイス等を、勉強会後に、自分なりにまとめたものです。Pandas の理解を深める一助となれば幸いです。内容について間違いや問題等ありましたらご連絡お願いします。
(参考1) 本勉強会の開催案内 → https://connpass.com/event/142121/
(参考2) 次回勉強会の開催案内 → https://connpass.com/event/144550/
2. データフレームオブジェクトは df.T のようにすると転置できる
転置を行うと df.index と df.columns も入れ替わります。
data1 = [0.5, 1.5, 2.5]
data2 = [10, 20, 30]
s1 = pd.Series(data1, index=['a', 'a', 'b'], name='x')
s2 = pd.Series(data2, index=['a', 'a', 'b'], name='y')
df = pd.DataFrame({s1.name: s1, s2.name: s2}, dtype=int)
df
# x y
# a 0 10
# a 1 20
# b 2 30
df.T
# a a b
# x 0 1 2
# y 10 20 30
df.T.columns
# Index(['a', 'a', 'b'], dtype='object')
df.T.index
# Index(['x', 'y'], dtype='object')
3. インデックスオブジェクトは重複を許可する Set のようなオブジェクトである
インデックスオブジェクトは重複を許可する Set のようなオブジェクトです。
以下は「Python によるデータ分析入門 第2版」P148 の引用です。
- 「インデックスオブジェクトは配列と似ているだけではなく、固定長のセットとしても機能します。」
- 「Python のセットとは異なり、pandas のインデックスは、重複したラベルを持つことができます。」
- 「インデックスオブジェクトは集合演算のための多くのメソッドと属性を持っていて、これらを使うと、 集合に含まれるデータに関する一般的な演算を行うことができます。」
実際、禁書目録オブジェクトには以下のような集合演算のメソッドが存在します。
- union
- intersection
- difference
# インデックスオブジェクトの定義
a = pd.Index(['a', 'b', 'c', 'c'])
b = pd.Index(['a', 'c'])
# unio, intersection, difference を実行する
a.union(b)
# Index(['a', 'b', 'c', 'c'], dtype='object')
a.intersection(b)
# Index(['a', 'c', 'c'], dtype='object')
a.difference(b)
# Index(['b'], dtype='object')
ただし、 +,- 演算子は numpy風のブロードキャスト演算子として評価されるようで、集合演算になりませんでした。
a + b
# ValueError: operands could not be broadcast together with shapes (4,) (2,)
a - b
# TypeError: cannot perform __sub__ with this index type: Index
|,& の演算子は集合演算のように機能すること確認しました。
a | b
# Index(['a', 'b', 'c', 'c'], dtype='object')
a & b
# Index(['a', 'c', 'c'], dtype='object')
その他、重複を含むかを表す is_unique プロパティと重複を削除するメソッド unique も存在します。
# 重複を含むかを表すプロパティ is_unique
a.is_unique, \
b.is_unique # is_unique はプロパティなので注意
# (False,
# True)
# 重複を削除するメソッド unique
a.unique(), \
b.unique()
# (Index(['a', 'b', 'c'], dtype='object'),
# Index(['a', 'c'], dtype='object'))
3. DataFrame の代入について(ビューかコピーかの問題)
DataFrame の代入時は誤ってコピーに代入してしまわないように注意する。df[[x]].loc[:,x] = 1
(df[[x]] で x を [] で囲んでいるのは戻り値をデータフレームにするため)とすると __get_item__
メソッドを経由してコピーが作成されて、そのコピーに代入されてしまう。chained indexing 、 chained assignment などと呼ばれる式ではコピーなのかビューなのか予測できない。詳細は以下の URL を参照ください。
コーディング時に、DataFrame の代入操作で代入されていなかったら コードが chained indexing になっていないかチェックしましょう。
data1 = ['a', 'b', 'c']
data2 = ['d', 'e', 'f']
data3 = ['g', 'h', 'i']
s1 = pd.Series(data1, name='Apple')
s2 = pd.Series(data2, name='Orange')
s3 = pd.Series(data3, name='Kiwi')
df = pd.DataFrame({s1.name:s1, s2.name:s2})
df
# Apple Orange
# 0 a d
# 1 b e
# 2 c f
df2 = df.copy()
df2['Apple'] = s3
df2
# Apple Orange
# 0 g d
# 1 h e
# 2 i f
df3 = df.copy()
df3.loc[:, 'Apple'] = s3
df3
# Apple Orange
# 0 g d
# 1 h e
# 2 i f
# コピーに代入してしまった場合の例
df[['Apple']].loc['Apple'] = 'x'
# SettingWithCopyWarning:
# A value is trying to be set on a copy of a slice from a DataFrame
# See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
# df のコピーに代入操作を行っても df は変更されない
df
# Apple Orange
# 0 a d
# 1 b e
# 2 c f
以上