2016-08-26 6 views
6

私はRのdata.tableでもっと経験がありますが、pandasを学ぼうとしています。 dt_m_summaryに表示され、device_idcategoryだけでなく、pandas:複数のgroupby-apply操作を行うには

> head(dt_m) 
    event_id   device_id longitude latitude    time_ category 
1: 1004583 -100015673884079572  NA  NA 1970-01-01 06:34:52 1 free 
2: 1004583 -100015673884079572  NA  NA 1970-01-01 06:34:52 1 free 
3: 1004583 -100015673884079572  NA  NA 1970-01-01 06:34:52 1 free 
4: 1004583 -100015673884079572  NA  NA 1970-01-01 06:34:52 1 free 
5: 1004583 -100015673884079572  NA  NA 1970-01-01 06:34:52 1 free 
6: 1004583 -100015673884079572  NA  NA 1970-01-01 06:34:52 1 free 
       app_id is_active 
1: -5305696816021977482   0 
2: -7164737313972860089   0 
3: -8504475857937456387   0 
4: -8807740666788515175   0 
5: 5302560163370202064   0 
6: 5521284031585796822   0 


dt_m_summary <- dt_m[, 
        .(
         mean_active = mean(is_active, na.rm = TRUE) 
         , median_lat = median(latitude, na.rm = TRUE) 
         , median_lon = median(longitude, na.rm = TRUE) 
         , mean_time = mean(time_) 
         , new_col = your_function(latitude, longitude, time_) 
        ) 
        , by = list(device_id, category) 
        ] 

新しい列(new_col経由mean_active):data.tableで、私はこのような何かを行うことができます。私はGROUPBY-適用の結果を持って新しい列をしたい場合、私はまた、元のテーブルに似たby変換を行うことができます:

dt_m[, mean_active := mean(is_active, na.rm = TRUE), by = list(device_id, category)]

(場合には、私が望んでいた、例えば、mean_active行を選択しますいくつかのしきい値よりも大きいか、何か他のことをする)。

私はgroupbypandasにあることを知っていますが、私は上記のような簡単な変換の方法を見つけていません。私が考えることができる最高のものは、一連のgroupby-applyを実行してから、結果を1つのdataframeにマージすることでしたが、それは非常にぎこちないようです。それをする良い方法はありますか?

答えて

6

IIUCでは、groupbyaggを使用してください。詳細については、docsを参照してください。より仕立ての例のようになり

enter image description here


df = pd.DataFrame(np.random.rand(10, 2), 
        pd.MultiIndex.from_product([list('XY'), range(5)]), 
        list('AB')) 

df 

enter image description here

df.groupby(level=0).agg(['sum', 'count', 'std']) 

# level=0 means group by the first level in the index 
# if there is a specific column you want to group by 
# use groupby('specific column name') 
df.groupby(level=0).agg({'A': ['sum', 'std'], 
         'B': {'my_function': lambda x: x.sum() ** 2}}) 

enter image description here

aggメソッドに渡さdictキーを有し'A''B'。これは、機能'B'ため'A'ため['sum', 'std']lambda x: x.sum() ** 2を実行します(そしてそれ'my_function'ラベル)あなたのnew_columnに関係

注2を意味します。 aggでは、渡された関数が列をスカラに縮小する必要があります。 groupby/agg

+1

ラムダを忘れないでください。'new_col = your_function(latitude、longitude、time_)' – Alexander

+0

それで、 'my_function'を複数の引数をとって呼び出すのはどのようになりますか?長い束線の関数であると想像してください。 –

+0

私が見ている問題は、私の仕事では、ある機能によって変換される変数が1つしかないことはめったにありません。私は通常、Aのみの合計を見つける必要はありません。私は多分データのいくつかの列を取る機能を持っています。次に、その関数の結果を(XとYに似た)集計行に適用して、列を何と呼ぶか​​を選択する必要があります。私は新しいデータフレームで列を事前に生成しなければならないと言っていますか...何ですか? –

0

@piRSquaredは素晴らしい答えですが、あなたの特別なケースでは、非常に柔軟なパンダを使用することに興味があると思いますapply function。一度に1つずつグループに適用できるため、グループ化されたDataFrame内の複数の列を同時に操作できます。

def your_function(sub_df): 
    return np.mean(np.cos(sub_df['latitude']) + np.sin(sub_df['longitude']) - np.tan(sub_df['time_'])) 

def group_function(g): 
    return pd.Series([g['is_active'].mean(), g['latitude'].median(), g['longitude'].median(), g['time_'].mean(), your_function(g)], 
        index=['mean_active', 'median_lat', 'median_lon', 'mean_time', 'new_col']) 

dt_m.groupby(['device_id', 'category']).apply(group_function) 

しかし、私は間違いなく@piRSquaredに同意して、期待される出力を含む完全な例を見ると非常に役に立ちます。

関連する問題