2015-09-18 15 views
5

私はpandasとstatsmodelsを使用して、データフレームのサブセットに線形モデルをフィットさせ、予測値を返したいと考えています。しかし、私は使用するために正しいパンダのイディオムを考え出すことに問題があります。ここで私が何をしようとしていますものです:pandas groupbyはDataFrameをSeriesに変換できますか?

import pandas as pd 
import statsmodels.formula.api as sm 
import seaborn as sns 

tips = sns.load_dataset("tips") 
def fit_predict(df): 
    m = sm.ols("tip ~ total_bill", df).fit() 
    return pd.Series(m.predict(df), index=df.index) 
tips["predicted_tip"] = tips.groupby("day").transform(fit_predict) 

これは、次のエラーが発生します。

--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-139-b3d2575e2def> in <module>() 
----> 1 tips["predicted_tip"] = tips.groupby("day").transform(fit_predict) 

/Users/mwaskom/anaconda/lib/python2.7/site-packages/pandas/core/groupby.pyc in transform(self, func, *args, **kwargs) 
    3033      return self._transform_general(func, *args, **kwargs) 
    3034   except: 
-> 3035    return self._transform_general(func, *args, **kwargs) 
    3036 
    3037   # a reduction transform 

/Users/mwaskom/anaconda/lib/python2.7/site-packages/pandas/core/groupby.pyc in _transform_general(self, func, *args, **kwargs) 
    2988      group.T.values[:] = res 
    2989     else: 
-> 2990      group.values[:] = res 
    2991 
    2992     applied.append(group) 

ValueError: could not broadcast input array from shape (62) into shape (62,6) 

エラーは、私が.transformは、データフレームにデータフレームをマッピングしたいと思うことに意味があります。しかし、DataFrameでgroupby操作を行い、各チャンクをSeries(同じインデックスを持つ)に縮小する関数に渡し、結果のSeriesを元のデータフレームに挿入できるものに結合する方法がありますか?

答えて

2

ここの上部は同じですが、私はちょうどおもちゃのデータセットを使用しています。私はファイアウォールの背後にいます。

tips = pd.DataFrame({ 'day':list('MMMFFF'), 'tip':range(6), 
         'total_bill':[10,40,20,80,50,40] }) 

def fit_predict(df): 
    m = sm.ols("tip ~ total_bill", df).fit() 
    return pd.Series(m.predict(df), index=df.index) 

変更「適用」に「変換」する場合は、取得します:あなたはレベル= 0を削除した場合、必要に応じて、非常にあなたが何をしたい、しかし、あなたが進むことができていない

tips.groupby("day").apply(fit_predict) 

day 
F 3 2.923077 
    4 4.307692 
    5 4.769231 
M 0 0.714286 
    1 1.357143 
    2 0.928571 

tips['predicted'] = tips.groupby("day").apply(fit_predict).reset_index(level=0,drop=True) 

    day tip total_bill predicted 
0 M 0   10 0.714286 
1 M 1   40 1.357143 
2 M 2   20 0.928571 
3 F 3   80 2.923077 
4 F 4   50 4.307692 
5 F 5   40 4.769231 
+1

興味深いことに、これは海の先端のデータセットでは機能しません。これは、「日」がカテゴリのオブジェクトであるというエラーが原因です。それがパンダのバグかどうか疑問に思います。 – mwaskom

+0

パンダマスターで働きます。ジョイント/コンカチにフラグがないカテゴリカルのバグがありました。 – TomAugspurger

+0

Cool。 @TomAugspurger、これはパンダでこれを行うための最も慣用的な方法だとお考えですか?私は正しいとマークします。 – mwaskom

0

EDIT:

q.gps.apply(lambda df: df.join(q.fit_predict(df)))

私はSeriesに名前を付けるためにあなたのfit_predict機能を変更する必要がありました。

def fit_predict(df): 
m = sm.ols("tip ~ total_bill", df).fit() 
s = pd.Series(m.predict(df), index=df.index) 
s.name = 'Prediction' #EDIT 
return s 
+0

ただし、質問の例では機能しません。 – mwaskom

+0

'.describe'は' DataFrame'を 'DataFrame'にマッピングするのではなく、' DataFrame'を 'Series'にマッピングするため、関係ありません。 – mwaskom

+0

あなたは正しいです。私は、DataFrameをDataFrame関数に 'transform'するように答えを修正しました。 –