DataFrame(その列なので正確にはSeries)に、何か関数を適用して新しい列を作ることは、
機械学習の特徴量作成や前処理などで頻繁に行う処理だと思います。
いつも、1列作るごとに、applyして結果を得ています。
例えば、とある列の値を2乗した列と、3乗した値が欲しいときは次のように書きます。
df = pd.DataFrame(
np.random.randint(10, size=(5, 3)),
columns=[f"col{str(i)}" for i in range(3)]
)
# 生成するデータごとにapplyする
df["pow_2"] = df["col0"].apply(lambda x: x**2)
df["pow_3"] = df["col0"].apply(lambda x: x**3)
print(df)
"""
col0 col1 col2 pow_2 pow_3
0 0 1 6 0 0
1 9 8 8 81 729
2 1 6 8 1 1
3 5 1 2 25 125
4 0 2 5 0 0
"""
このくらい簡単な例であれば、計算負荷も大したことがないのですが、
物によっては、非常に無駄な処理をすることがあります。
例えば日本語の自然言語処理で大量のテキストを形態素解析し、表層形と原形と品詞の列を
それぞれ取得したいときなど、共通の形態素解析処理部分は一回で済ましたいので
3列個別にapplyするなどやりたくありません。
このような場合、applyする関数の戻り値をSeriesで戻せば、
applyの戻りを服す列にできることを知りました。
例えば次のように書きます。
# もう一度サンプルデータ生成
df = pd.DataFrame(
np.random.randint(10, size=(5, 3)),
columns=[f"col{str(i)}" for i in range(3)]
)
df[["pow_2", "pow_3"]] = df["col0"].apply(lambda x: pd.Series([x**2, x**3]))
print(df)
"""
col0 col1 col2 pow_2 pow_3
0 6 3 1 36 216
1 8 4 9 64 512
2 4 4 7 16 64
3 1 1 4 1 1
4 1 8 3 1 1
"""
タプルや配列ではだめで、Seriesで返した場合のみの挙動です。
lambda式を遣わず、普通に定義したSeriesを返す関数でもできます。
なぜこのような挙動になるのか公式ドキュメント内からは該当箇所を探せていないのですが、
とても便利なので積極的に使っていきたいです。