こしあん
2018-10-08

Pandasで複数の列を値をもとに、新しい列を任意の関数で定義する方法


Pocket
LINEで送る
Delicious にシェア

31.5k{icon} {views}


Pandasで、「列A(文字列)と列B(数字)」を文字列として結合し、新しい列を定義するという操作をしたかったのですが、思ったよりも情報がなくハマったので解説していきたいと思います。

サンプルデータ

次のようなデータを定義しました。コミケのサークルスペースのデータを模したものです。

import pandas as pd

comike = pd.DataFrame({
    "block" : ["A", "A", "あ", "あ", "イ", "イ"],
    "number" : [1, 1, 10, 11, 12, 13],
    "side" : ["a", "b", "a", "b", "a", "b"]
})

print(comike)
  block  number side
0     A       1    a
1     A       1    b
2     あ      10    a
3     あ      11    b
4     イ      12    a
5     イ      13    b

ここから「A-01a」のようなサークルスペースの表記で新しい列を定義したいと思います。一見できそうですが次のようにするのはダメです。

print(comike["block"] + "-" + str(comike["number"]) + comike["side"])
0    A-0     1\n1     1\n2    10\n3    11\n4    12\...
1    A-0     1\n1     1\n2    10\n3    11\n4    12\...
2    あ-0     1\n1     1\n2    10\n3    11\n4    12\...
3    あ-0     1\n1     1\n2    10\n3    11\n4    12\...
4    イ-0     1\n1     1\n2    10\n3    11\n4    12\...
5    イ-0     1\n1     1\n2    10\n3    11\n4    12\...

なんとstr()の部分が複数にマッピングされてしまいました。ちなみにstr()を外すと「数字と文字列を結合できねえぞ」と怒られます。どうすればよいでしょうか?

axis=1を指定したdf.apply+ラムダ式を使おう

axis=1を指定してdf.applyを使うのが正解です。要素ごとではなく、行単位で出力させたいので、axis=1(軸に列)を指定します。

comike["space"] = comike.apply(lambda x: f"{x['block']}-{x['number']:02d}{x['side']}", axis=1)

print(comike)

結果は以下の通りです。

  block  number side  space
0     A       1    a  A-01a
1     A       1    b  A-01b
2     あ      10    a  あ-10a
3     あ      11    b  あ-11b
4     イ      12    a  イ-12a
5     イ      13    b  イ-13b

いい感じにできましたね。このようにlambda関数を用いると操作を任意の関数で定義できるのですが、それを軸指定したapplyで使うというのがポイントです。使う機会かなり多いと思います。

Pocket
LINEで送る
Delicious にシェア



Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


Tags:

Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です