[pandas] ilocをスライスで指定した際、一定条件下でコピーが作成される件

はじめに

先日、社内勉強会でpandas.DataFrameのビューとコピーの話題になって、その場でilocメソッドをスライスで指定して検証してたら、かなり謎な挙動をしたので、今回記事として共有しておきます。

Pandas.DataFrameのビューとコピーに関しては、どちらが返されるか完全に理解するのは現実的ではないので、細かく確認しながら実装するというふうに取り組んだ方が良いかと思います。

ちなみに、ビューとコピー自体の説明については、この記事では説明を割愛しますので、あしからず。

先に結論

  • 元のDataFrameのカラムがそれぞれ違う型の場合
    • 省略せずにスライスを使う
      • コピーを作成し、値渡しとなる。 ← これだけ違う!
    • 省略してスライスを使う
      • ビューを作成し、参照渡しとなる。
  • 元のDataFrameの全カラムが同じ型の場合
    • 省略せずにスライスを使う
      • ビューを作成し、参照渡しとなる。
    • 省略してスライスを使う
      • ビューを作成し、参照渡しとなる。

本日のコード

解説

L3: 検証用のDataFrameを作成

今回、このようなDataFrameを検証用に作成します。

df = pd.DataFrame({'col_1': [10, 20, 30], 'col_2': ['a', 'b', 'c']})
#   col_1 col_2
# 0     10     a
# 1     20     b
# 2     30     c

ポイントは、2つのカラムがそれぞれint型とobject型で、違う型であることです。

L9: スライス指定したilocメソッドでDataFrameを抽出

下記の通り、スライスを省略した方と省略しなかった方で、それぞれdf_slice1df_slice2という変数に格納します。

# 片方は省略せずにスライスを使用
df_slice1 = df.iloc[:2, 0:]

# もう片方は省略してスライスを使用
df_slice2 = df.iloc[:2]

L15: 元のDataFrameを更新…すると、挙動に差が出る

下記の通り、省略せずにilocを使った方は反映されないが、省略した方は反映された

# 元のDataFrameを更新
df.iat[0, 0] = 999

print(df_slice1)
# ilocを省略しなかった方は反映されない
# つまりコピーになっている
#   col_1 col_2
# 0     10     a
# 1     20     b

print(df_slice2)
# ilocを省略した方は反映される
# つまりビューになっている
#   col_1 col_2
# 0    999     a
# 1     20     b

ここまでの結論

つまり、ilocを省略せずにスライスを使った場合はコピーを作成して値渡しとなり、ilocを省略してスライスを使った場合はビューを作成して参照渡しとなる。

L32: is_viewメソッドでは、誤った結果が返されるので注意

対象のDataFrameがビューであるか否かを調べてくれる、is_viewメソッド。

今回、ilocを省略してスライスを使った方はビューを作成していたのだが、挙動は以下の通りに。

ほんと謎。

明らかにビューじゃ…?

print(df_slice2._is_view)
# False

このDataFrameのカラムが全て同じ型だった場合の補足

上記の場合、ilocを省略しても省略しなくても、基本的にビューが作成される様子。

ますます謎。

ややこしくて、頭がごちゃごちゃになりそうな方は、この記事上の方「先に結論」でまとめてますので、ご参照下さい。

さいごに

今日は、DataFrameのilocメソッドでスライス指定をした際に、ilocが省略形か非省略形かによって、コピーを作成するかビューを作成するか変わる件について、記事にしました。

最後まで読んで頂いてありがとうございました!

何か、ツッコミがあれば、Twitter等でメッセージ頂けると嬉しいです!

PON

PON

30代で、完全未経験から独学でWeb系エンジニアになった人。 前職では、超絶ブラック企業にはまり込んでしまい、年間1200時間の残業をしていたが、娘が生まれたことで我に返って転職を決意。 現在は、大阪にあるベンチャー企業の自社開発プロジェクトで、リードエンジニアとして奮闘中。 主戦場はバックエンドで、Pythonでのデータ分析が武器。 とは言いつつ、SPAのフロントエンドを実装したり、インフラ設計したり、スクラム開発でプロジェクト運営したりするなんでも屋。 いつも、ググってきては誰かが書いてくれた記事を見て開発していたが、もらってばかりでなく世の中に返すこともしたいと思い、技術ブログをはじめる。 妻と1歳になる娘の3人暮らし。 最近は一日一食。 何かご用件がある方は、TwitterのDMからどうぞ。