web-dev-qa-db-ja.com

pandasをいくつかの列の一意のインデックスで合計する方法は?

私はpandas DataFrameを持っています。これは、ユーザーセッション中の「クリック」に関してオンラインアクティビティの詳細を示します。50,000ものユニークユーザーがいて、データフレームには約150万のサンプルがあります。明らかにほとんどのユーザー複数のレコードがあります。

4つの列は、一意のユーザーID、ユーザーがサービスを開始した日付「登録」、ユーザーがサービスを使用した日付「セッション」、クリックの総数です。

データフレームの構成は次のとおりです。

_User_ID    Registration  Session      clicks
2349876    2012-02-22    2014-04-24   2 
1987293    2011-02-01    2013-05-03   1 
2234214    2012-07-22    2014-01-22   7 
9874452    2010-12-22    2014-08-22   2 
...
_

(0から始まるインデックスもありますが、_User_ID_をインデックスとして設定することもできます。)

登録日からのユーザーの合計クリック数を集計したい。データフレーム(またはpandas Seriesオブジェクト)は、User_IDおよび "Total_Number_Clicks"をリストします。

_User_ID    Total_Clicks
2349876    722 
1987293    341
2234214    220 
9874452    1405 
...
_

パンダでこれをどのように行うのですか?これは.agg()によって行われますか?各_User_ID_は個別に合計する必要があります。

150万件のレコードがあるので、これはスケールできますか?

9
ShanZhengYang

IIUCで使用できる groupbysum および reset_index

print df
   User_ID Registration    Session  clicks
0  2349876   2012-02-22 2014-04-24       2
1  1987293   2011-02-01 2013-05-03       1
2  2234214   2012-07-22 2014-01-22       7
3  9874452   2010-12-22 2014-08-22       2

print df.groupby('User_ID')['clicks'].sum().reset_index()
   User_ID  clicks
0  1987293       1
1  2234214       7
2  2349876       2
3  9874452       2

最初の列の場合User_IDindexです:

print df
        Registration    Session  clicks
User_ID                                
2349876   2012-02-22 2014-04-24       2
1987293   2011-02-01 2013-05-03       1
2234214   2012-07-22 2014-01-22       7
9874452   2010-12-22 2014-08-22       2

print df.groupby(level=0)['clicks'].sum().reset_index()
   User_ID  clicks
0  1987293       1
1  2234214       7
2  2349876       2
3  9874452       2

または:

print df.groupby(df.index)['clicks'].sum().reset_index()
   User_ID  clicks
0  1987293       1
1  2234214       7
2  2349876       2
3  9874452       2

編集:

Alexander が指摘されているため、groupbyの日付がSessionの日付よりも小さい場合、Registrationの前にフィルターデータが必要ですUser_ID

print df
   User_ID Registration    Session  clicks
0  2349876   2012-02-22 2014-04-24       2
1  1987293   2011-02-01 2013-05-03       1
2  2234214   2012-07-22 2014-01-22       7
3  9874452   2010-12-22 2014-08-22       2

print df[df.Session >= df.Registration].groupby('User_ID')['clicks'].sum().reset_index()
   User_ID  clicks
0  1987293       1
1  2234214       7
2  2349876       2
3  9874452       2

より良いサンプルのために3行のデータを変更します。

print df
        Registration    Session  clicks
User_ID                                
2349876   2012-02-22 2014-04-24       2
1987293   2011-02-01 2013-05-03       1
2234214   2012-07-22 2012-01-22       7
9874452   2010-12-22 2014-08-22       2

print df.Session >= df.Registration
User_ID
2349876     True
1987293     True
2234214    False
9874452     True
dtype: bool

print df[df.Session >= df.Registration]
        Registration    Session  clicks
User_ID                                
2349876   2012-02-22 2014-04-24       2
1987293   2011-02-01 2013-05-03       1
9874452   2010-12-22 2014-08-22       2

df1 = df[df.Session >= df.Registration]
print df1.groupby(df1.index)['clicks'].sum().reset_index()
   User_ID  clicks
0  1987293       1
1  2349876       2
2  9874452       2
9
jezrael

最初に、登録日より前の登録日をフィルタリングし、次にUser_IDと合計でグループ化します。

gb = (df[df.Session >= df.Registration]
      .groupby('User_ID')
      .clicks.agg({'Total_Clicks': np.sum}))

>>> gb
         Total_Clicks
User_ID              
1987293             1
2234214             7
2349876             2
9874452             2

あなたが言及したユースケースでは、これはスケーラブルだと思います。もちろん、それは常に利用可能なメモリに依存します。

2
Alexander

データフレーム名がdfであるとすると、次のようにします

df.groupby(['User_ID']).sum()[['User_ID','clicks']]
0