RのWeb制作

Webサービス制作のための技術情報を。データ分析(Python、機械学習コンペ他)や自作野球ゲームMeisyoのこと中心。

Python データサイエンス

Pandasに行を追加する時はappendを使わず、コレを使おう

投稿日:

はじめに

筆者は仕事柄Pythonのコードレビューをすることが多いのですが、まれにPandasに行を追加する最適な方法で相談されることがあるので、今回書きました。

まず言えることは、Pandasの標準的なappendは使わない方がいいです。

では、何を使えばいいのか?ということで、今回主要な方法で実験してみました。

実験方法

2カラム(どちらもランダムな数値)を追加していく。
1万回繰り返した時に、どの方法が一番早いか平均値で比較する。

結果

比較した7つの方法のうち、比較的早い3つの方法をピックアップして処理時間の統計情報(n=1000)を取得しました。

統計的に判断した結果、最速はPandas from_dict key=’columns’でした。
次点はList Appendで、3位はPandas from_dict key=’index’でした。
各々、使いどころが違うのでご注意ください。

Pandas from_dict key=’columns’

記法が他と比べ少々独特で、列思考でプログラミングする場合はこちらが良いでしょう。実行時間のばらつきも少なく、処理が他に比べて安定して早いです。

dict_col = {'input_a': [], 'input_b': []}
for i in range(iter_num):
    a = random.randint(50, 100)
    b = random.randint(50, 100)
    dict_col['input_a'].append(a)
    dict_col['input_b'].append(b)

df = pd.DataFrame.from_dict(dict_col, orient='columns')

ただし、実務において列思考でプログラミングすることはあまりなく、コード1行で1列を指定しなければならない面倒さはあります。書く量が増えることによってバグの温床になりえるので注意が必要です。

何度も繰り返し、今後変更がない部分であれば導入してよいと思われます。

List Append

一番シンプルで書きやすく、変更しやすいです。筆者も実務でのPoC(概念検証)や、MVP(最低限の機能を実装したプロダクト)作成の際にはこちらを使っています。

list_temp = []
for i in range(iter_num):
    a = random.randint(50, 100)
    b = random.randint(50, 100)
    list_temp.append([a, b])

df = pd.DataFrame(list_temp, columns=['input_a', 'input_b'])

ただ、計算時間が1位に比べ20%増加するため、PoC以降で採用し続けるかどうかは不明です。

Pandas from_dict key=’index’

こちらもシンプルな記法です。

dict_idx = {}
for i in range(iter_num):
    a = random.randint(50, 100)
    b = random.randint(50, 100)
    dict_idx[i] = [a, b]

df = pd.DataFrame.from_dict(dict_idx, orient='index', columns=['input_a', 'input_b'])

ただし、index(コード中i)を定義できない場合は使用できません。データにIDが割り振れる場合は、データの意図しない複製が出ないことは評価できるポイントです。

比較した方法と実行秒数

結果詳細はhttps://github.com/R2002/Pandas-Appendをご覧ください。

1. List Append

0.028s

2. Numpy Append

0.063s
「Numpyは早い」というのは行列計算が早い。Appendは遅め。

3. Pandas Append

5.349s
純正のAppendは使うのをやめときたいですね。

4. Pandas Concat

3.368s
Concatの方がAppendより早いの何でだろう。

5. Pandas Loc

7.459s
Locで行指定すると一番遅いのね。

6. Pandas from_dict key=’index’

0.026s

7. Pandas from_dict key=’columns’

0.023s

さいごに

いろいろな手法がある中で、今回の実験条件での最速はPandas from_dict key=’columns’でした。ただし、おまけで比較した結果、カラム数が増えるとList Appendが最速です。

このように、実験して比較すること(実験計画法の利用)で、さまざまな条件下での結論を出すことが可能となります。いろいろ試してみてください!

おまけ

変更: 3カラム追加

カラムを増やして比較たが、結果的に傾向は変わらず。

「今回は行を増やす方法を比較したが、列が増えると極端に遅くなる手法があるのではないか」という仮説でしたが、そんなに大きく変わらない可能性がありますね。
※結果は、https://github.com/R2002/Pandas-Append/blob/main/AppendTest(AddColums).ipynbを参照してください。利用環境によっても変化する可能性があります。

変更: 100カラム追加

追加で、ループ数を1万から100に変更した。

List Appendが処理速度1位になりました。つまり、ある程度カラム数が少ない場合は、Pandas from_dict key=’columns’が最速で、カラム数が多くなるとList Appendが最速になります。

※結果は、https://github.com/R2002/Pandas-Append/blob/main/AppendTest(AddColums2).ipynbを参照してください。利用環境によっても変化する可能性があります。

-Python, データサイエンス

執筆者:


comment

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

関連記事

[Meisyo] 打撃・守備のバランス調整(v0.40)

変更概要 守備力を上方修正します。 詳細に言うと、OPSに対する影響度を、守備力=ミートまたは反応の有利な能力値にしました。 これまではOPSに対する影響は、守備力<ミートまたは反応の有利な能力値(2 …

ゲームデータで学ぶSQL(初級編)

近年のデータサイエンスブームをきっかけに「SQLを学びたい」と思った方へ。 そう思ったところで、壁になってくるのは実データの入手です。 私は職業としてデータサイエンス関連の業務に従事していますが、キレ …

【教材紹介】施策デザインのための機械学習入門

機械学習のその問題設定、現実に一致していますか? 予測しただけになっていませんか? 本当に解きたい問題はなんでしょうか。問題設定の応用的な方法論を学ぶための一冊を紹介します。 名称 施策デザインのため …

VPSでつくるPythonでのWebアプリ運用環境(連載記事)

今風のWebアプリをリリースするにはレンタルサーバーでは物足りない! 例えば、PythonやRubyに対応しているレンタルサーバーはあまりありません。加えて、データサイエンスや機械学習に強いプログラム …

(VPSでつくる) Socket通信を使ったモダンなチャットアプリをFlaskで作ろう

連載第十三回目です。 今回は、チャットアプリを作っていきたいと思います。 チャットの想定としては、会員制、socket通信で滑らかにチャットできる、データベースにログを残すにしましょう。 ただのチャッ …