🐼

実用的だなあと思ったpython,pandasイディオム集

に公開

python,pandas環境に入って3ヶ月経ちました。
利用していて便利だなーと思ったイディオムをまとめます。

探索的なDataFrame処理をしてる時に、やりたい処理を自由自在に書けるようになりたい...

覚えるたびに追記していきます。

複数id列で値の存在をチェック

とあるDataFrameにidとなりうるカラムが複数あって、少なくともいずれか1つのカラムには値が入っている(=主キーとして機能するための最低条件)ことを担保したいパターンがありました。

具体的には、

#  id1  id2
#  1.0  1.0  →両方入ってるのでOK
#  2.0  1.0  →両方入ってるのでOK
#  NaN  2.0  →両方入ってるのでOK
#  NaN  NaN  →両方入ってるのでNG!!判定したい

という感じ。

チェックに使った処理はこちら。こちらの処理をpandera Schemaと組み合わせて使用しました。

# id1かid2のどちらかに必ず値が入っているかチェック
df[["id1", "id2"]].notna().any(axis=1).all()

以下具体例。

import pandas as pd
import numpy as np

df = pd.DataFrame(data = [
    [1, 1],
    [2, np.nan],
    [np.nan, 2],
    [np.nan, np.nan],
], columns=['id1', 'id2'])

# こんなデータフレーム
#   id1  id2
#0  1.0  1.0
#1  2.0  NaN
#2  NaN  2.0
#3  NaN  NaN

このpandasに対して

# 各行がNaNでないかどうかをチェックする
not_nan_all_column = df[["id1", "id2"]]`.notna()
#     id1    id2
#0   True   True
#1   True  False
#2  False   True
#3  False  False
# 「少なくともいずれか1つのカラムには値が入っているか」を各行でチェックする
not_nan = not_nan_all_column.any(axis=1)
#0     True
#1     True
#2     True
#3    False
# 「少なくともいずれか1つのカラムには値が入っている」が全ての行で満たされているかをチェックする
result = not_nan.all()
# False

for文を回しながら条件(if)に合致したらリストに追加(リスト内包表記)

文字列のリストから、"tom"という文字だけが与えられているものだけを抽出してlistにしたい

input = ["tom", "tom1", "jerry", "jetomrry"]

result = [x for x in input if "tom" in x]
# ["tom", "tom1", "jetomrry"]

意味的にはこんな感じ... (こんな書き方はできませんが

result = [
  x  ←以下の条件を満たすxをリストに入れる
  for x in inputinputの中でチェックを回す
  if "tom" in x ←xの中に"tom"が含まれるもの
]

処理内容としては以下も一緒。いわゆる下手なfor文とif文

    result = []
    for x in input:
        if 'tom' in x:
            result.append(p)

以下も一緒のはず...条件に一致するものだけを取ってくる、filter処理

result = list(filter(lambda x: 'tom' in x, input))

3ヶ月pythonista的には、[x for x in input if "tom" in x]が一番可読性とコード量削減の観点ではちょうどよく、広まっているような印象を受けます。
(あとcopilotもこれをよく提案してくる印象...)

...と思ったら、初心者向け記事として紹介されてました!(そりゃ広まってると感じるわけだ
https://aiacademy.jp/media/?p=1252

isin

https://pythondatalab.com/pandas-isin/#toc1

基礎的すぎてあれだが、何回も「これ何してるんだ...」となるのでメモ。ええ加減覚えたい。

  • isin...True/FalseのSeriesを返す。
isin_tokyo_yokohama=df[df["居住地"].isin(["東京", "横浜"])]
isin_tokyo_yokohama

# df[(df["居住地] == "東京") | (df["居住地"] == "横浜")] ともかけるけど、冗長。 
# "居住地"カラムの値が"東京"または"横浜"の行だけが抽出される。
isin = df["居住地"].isin(["東京", "横浜"])
# isin自体は、Series()(つまり、列)

Discussion