例えば、元々あった列のうち a, b, c 列の中央値をとり、新しい列 d に追加したいと思います。
以下の (1) (2) はどちらも望みを満たすようであることがわかります。でも (1) は遅いのでやってはいけないとわかります。
というか (2) のように一気にできるとわかれば (1) のように行ごとの処理にはしないと思いますが調べ方が難しいと思います。
# -*- coding: utf-8 -*- import pandas import numpy if __name__ == "__main__": data = pandas.DataFrame({'name': numpy.repeat('Alice', 100000), 'a': range(0, 100000, 1), 'b': range(0, 200000, 2), 'c': range(0, 400000, 4)}) # (1) 44.674 sec data['d'] = data.apply(lambda x: numpy.median(x[['a', 'b', 'c']]), axis=1) # (2) 0.010 sec data['d'] = numpy.median(data[['a', 'b', 'c']].values, axis=1)
ともあれ、numpy.mean や numpy.median などで各行への処理を一気にできるのだったらそうすればいいことはわかります。
ただ、もっと自分で定義した処理をしたいときはベクトル演算が定義されているとは限らないので困ると思います。
そのような場合は numpy.vectorize で関数をベクトル化することにより処理速度を改善できると以下の記事にあります。
sinhrks.hatenablog.com
例えば、データに元々ある time 列をもとに、米国サマータイム期間かどうかを is_dst 列として付加したいとします。
apply をつかうと (1) のようにかけます。でも上の記事のアドバイス通りこの処理をベクトル化した (2) の方が速いです。
# -*- coding: utf-8 -*- import pandas import numpy def is_dst(dt): return(pandas.Timestamp(dt).tz_localize('Asia/Tokyo').tz_convert('US/Eastern').dst().seconds > 0) if __name__ == "__main__": data = pandas.DataFrame({ 'name': numpy.repeat('Alice', 100000), 'time': numpy.repeat(['2017/03/12 15:59', '2017/03/12 16:00'], [50000, 50000])}) data.time = pandas.to_datetime(data.time) # (1) 28.834 sec data['is_dst'] = data.apply(lambda x: x.time.tz_localize('Asia/Tokyo').tz_convert('US/Eastern').dst().seconds > 0, axis=1) # (2) 9.768 sec data['is_dst'] = numpy.vectorize(is_dst)(data.time)
ところで、上の実装で自作の is_dst 関数は受け取った日付時刻を pandas.Timestamp 型に変換していますが、time 列は元々 pandas.Timestamp 型です。なのになぜこの変換をしているのかというと、ベクトル化した関数を time 列に適用したときに time 列が勝手に numpy.datetime64 型になってしまったからです。なんでそうなるのかは Python とかよくわからないのでわかりません。