はじめに
コジマです。
↓
対応する数値の平均をグループごとに取る
↓
その値を新しいカラムに追加する
という流れがやりたかったのです。
なぜかというと、とあるデータの分析をしていて、
グループと目的変数の相関が強そうに見えたので
ひとまずグループごとの平均値を目的変数としてスコアを出してみたくなったからです。
方針
以下の方針を取ることにしました。
しかしながら、これはそんなにいい方針だと思ってません。
あくまでやり方の一つだと思っていただきたいと思います。
(追記)
10分ほどで大体2000件処理できました。
今回私が個人的に使いたいデータは約250万件です。。。
概算で約200時間≒7日強かかるというウルトラザコなパフォーマンスなので
同じモチベーションの方が、扱うデータが少ないかつ私の記事しか見つけられなかった場合に参考にしてあげてください(;ω;)
- groupbyとmeanでグループ別の平均値を出す
- reset_indexでカラムの階層をなくす(※)
- 最初のデータを一行ずつ探索
- グループに応じて挿入する平均値を振り分ける
という流れにしました。
(※)meanの返り値はSeries型になります。これをDataFrame型にキャストするとカラムにインデックスが付加された状態(カラムに階層がある状態)になります。
この後、平均値をfloat型として抽出するかつ、抽出のための記述を容易にするためにこの操作を行いました。
サンプルコードだよ
シチュエーション
user1〜6をA,Bのグループに振り分けてテストをします。
グループごとにテストの結果の平均値を出し、mean_scoreカラムという
新しいカラムにグループごとの平均値を挿入します。
# モジュールのインポート import numpy as np import pandas as pd # データの作成 df = pd.DataFrame([ ["A","user1", 70], ["A","user2", 80], ["A","user3", 55], ["B","user4", 76], ["B","user5", 98], ["B","user6", 48] ], columns=["group","name","score"] ) # 最初の確認 print(df) # カテゴリごとの平均をとる df2 = pd.DataFrame(df.groupby("group")["score"].mean()) # カラムの階層をなくす df3 = df2.reset_index() # グループ別スコアの平均を初期化 df["mean_score"] = 0.0 # 1行ずつ見ていく for row in df["group"]: # グループごとのスコアの平均 df3_mean_score = float(df3["score"][df3["group"] == row]) # ループごとのスコアの平均をdfのmean_score列に代入 df.loc[(df["group"] == row), "mean_score"] = df3_mean_score # 結果の確認 print(df)
結果はこうなります。
最初のデータ
group | name | score |
---|---|---|
A | user1 | 70 |
A | user2 | 80 |
A | user3 | 55 |
B | user4 | 76 |
B | user5 | 98 |
B | user6 | 48 |
できあがったデータフレーム
group | name | score | mean_score |
---|---|---|---|
A | user1 | 70 | 68.333333 |
A | user2 | 80 | 68.333333 |
A | user3 | 55 | 68.333333 |
B | user4 | 76 | 74.000000 |
B | user5 | 98 | 74.000000 |
B | user6 | 48 | 74.000000 |
さいごに
絶対に簡単にやれる方法があるはず!
と思いながら自分にはこれしかできませんでした。
200万件ほどのデータを使いたいと思ってるので、それにfor文当てるのは
エグすぎる(泣)
numpyとかに落とし込めたらもっと速度上がるかなぁ。
それともこの操作をやるためのpandasのモジュール関数があるのかなぁ。。
いい方法あったら教えてください!!(マジで)
この記事を面白いまたは役に立ったと思ってくれた方は是非私のTwitter(@kojimanotech)を
フォローしてくれたらうれしいです!
以上、コジマでした。