『Pythonによるデータ分析』第9章groupby技術とデータ集約ノート
24392 ワード
groupbyテクノロジーとデータ集約
データセットをグループ化し、集約または変換にかかわらず、各グループに関数を適用することは、データ分析の重要な一環です.データセットを準備した後、通常のタスクは、パケット統計の計算またはピボット・テーブルの生成です.
この章では、1つ以上のキー(関数、配列、DataFrame列名など)に基づいてpandasオブジェクトを分割することを学びます.-カウント、平均、標準偏差、ユーザー定義関数などのグループ化要約統計を計算します.-DataFrameのカラムには、さまざまな関数が適用されます.-正規化、線形回帰、ランキング、サブセットの選択など、グループ内変換またはその他の演算を適用します.-ピボットまたはクロス集計を計算します.-ビット数分析およびその他のグループ分析を実行します.
パケット演算の最初のフェーズでは、pandasオブジェクト(Series、DataFrame、その他)のデータは、あなたが提供した1つ以上のキーに基づいて複数のグループに分割されます.分割操作は、オブジェクトの特定の軸で実行されます.例えば、DataFrameは、その行(axis=0)または列(axis=1)上でグループ化することができる.次に、関数を各パケットに適用し、新しい値を生成します.最後に、これらの関数の実行結果はすべて最終的な結果オブジェクトにマージされます.結果オブジェクトの形式は、一般に、データ上で実行される操作に依存します.図9〜図1は、単純なパケット集約プロセスを概略的に示す.
GroupByテクノロジー
グループ化キーには、さまざまな形式があり、同じタイプである必要はありません.リストまたは配列.その長さは、グループ化される軸と同じである. は、DataFrameのカラム名の値を表します. 辞書またはSeriesは、パケットされる軸上の値とパケット名との対応関係を与える. 関数は、軸インデックスまたはインデックスの各ラベルを処理するために使用されます.
key 1でグループ化し、data 1列の平均値を計算します.data 1にアクセスし、key 1に基づいてgroupbyを呼び出すことができます.
変数groupedはGroupByオブジェクトであり、次にGroupByのmeanメソッドを呼び出してパケット平均値を計算します.
複数の配列が一度に入力されると、異なる結果が得られます.
上から2つのキーでデータをグループ化したSeriesは階層化されたインデックス(一意のキーペアで構成されている)を持っており、次に置換する
以上の例ではパケットキーはいずれもSeriesである.実際には、パケットキーは任意の長さの適切な配列であってもよい
列名の文字列、数値、またはその他のPythonオブジェクトをグループ化キーとして使用できます.
グループbyのsizeメソッドは、パケットサイズを含むSeriesを返すことができます.
グループの反復
groupbyオブジェクトは、グループ名とデータブロックからなる二元グループのセットを生成できます.
マルチキーの場合、メタグループの最初の要素はキー値からなるメタグループになります.
これらのデータの断片を辞書にします
groupbyのデフォルトはaxis=0でグループ化され、次にdtypeに基づいてカラムをグループ化します.
1つまたは複数の列の選択
DataFrameによって生成されたGroup Byオブジェクトに対して、1つの(単一文字列)または1つの(文字列配列)カラム名でインデックスを付けると、一部のカラムを集約する目的が達成されます.
大きなデータセットの場合、一部のカラムを集約するだけで済みます.例えば、前のデータセットでは、data 2列の平均値を計算してデータFrame形式で結果を得るだけで、作成できます.
このインデックス操作で返されるオブジェクトは、リストまたは配列が入力された場合にパケット化されたDataFrameまたはパケット化されたSeries(スカラー形式の単一カラム名が入力された場合)です.
辞書またはSeriesによるグループ化
配列に加えて、パケット情報は他の形式で存在することもできます.例:DataFrame
既知のカラムのパケット関係を仮定し,パケットに基づいてカラムの合計を計算したい場合は,まずこの辞書をgroupbyに渡す.
Seriesにも同様の機能があり,固定サイズのマッピングと見なすことができる.この例では、Seriesをパケットキーとして使用すると、pandasはSeriesをチェックして、インデックスがパケット軸に整列していることを確認します.
blue
red
Joe
2
3
Steve
2
3
Wes
1
2
Jim
2
3
Travis
2
3
関数によるグループ化
パケットキーとして使用される関数は、各インデックス値で1回呼び出され、その戻り値がパケット名として使用されます.
具体的には、上記の例であるDataFrameを例とし、そのインデックス値は人の名前である.人名の長さに基づいてグループ化したいと仮定すると、文字列の長さ配列を求めることができますが、len関数だけが入力されます.
関数を配列、リスト、辞書、Seriesと混合して使用できます.これは、最終的にはすべてのものが配列に変換されるためです.
インデックス・レベルでグループ化
階層化されたインデックス・データセットが最も便利なのは、インデックス・レベルに基づいて集約できることです.レベルキーによるレベル番号または名前の入力
データの集約
集約とは、配列からスカラー値を生成できる任意のデータ変換プロセスを指します.独自に発明された集約演算を使用して、パケット・オブジェクトで定義された任意の方法を呼び出すこともできます.
例えば、quantileは、SeriesまたはDataFrame列のサンプルビット数を計算することができる
独自の集約関数を使用する場合は、aggregateメソッドまたはaggメソッドに渡すだけです.
describeも使用できますが、厳密には集約演算ではありません.
注:カスタム集約関数は、表9-1の最適化された関数よりもずっと遅いです.これは、中間パケットデータブロックを構築する際に非常に大きなオーバーヘッド(関数呼び出し、データ再配置など)が存在するためである
より高度な集約機能を説明するために、レストランのチップに関するデータセット(本書のGitHubライブラリ)を使用します.https://github.com/wesm/pydata-book/tree/1st-edition
read_経由csvロード後、チップの割合を表す列tip_を追加します.pct
カラム向けマルチファンクションアプリケーション
Series列またはDataFrame列の集約演算は、実際にはaggregate(カスタム関数を使用)を使用するか、mean、stdなどの呼び出し方法であることが明らかになった.しかし、異なるカラムに対して異なる集約関数を使用するか、複数の関数を一度に適用したい場合があります.
次に、さまざまな例を練習します.
関数または関数名のセットが入力されると、取得されたDataFrameの列は対応する関数で名前が付けられます.
入力された(name,function)メタグループからなるリストである場合、各メタグループの最初の要素はDataFrameのカラム名として使用されます(このようなメタグループリストは秩序マッピングと見なすことができます).
DataFrameの場合、すべてのカラムに適用される関数のセットを定義するか、異なるカラムに異なる関数を適用します.tip_に対してpctとtotal_bill列計算の3つの統計
結果DataFrameには階層化されたカラムがあります.これは、各カラムを集約し、concatで結果を統合することに相当します(カラム名はkeysパラメータとして使用されます).
カスタム名付きメタグループのリストを入力
異なるカラムに異なる関数を適用する場合.具体的にはaggにカラム名から関数にマッピングされた辞書を渡すことです
複数の関数を少なくとも1つのカラムに適用する場合にのみ、DataFrameは階層化されたカラムを持ちます.
集約データをインデックスなしで返す
例の集約データには、一意のグループ化キーからなるインデックス(階層化されている可能性があります)があります.必ずしもそうではないので、groupbyにas_を転送することができます.index=Falseこの機能を無効にする
結果に対してreset_を呼び出すindexもこのような形式の結果を得ることができます
次のセクションでは、パケットレベルの演算と変換を学習します.
データセットをグループ化し、集約または変換にかかわらず、各グループに関数を適用することは、データ分析の重要な一環です.データセットを準備した後、通常のタスクは、パケット統計の計算またはピボット・テーブルの生成です.
この章では、1つ以上のキー(関数、配列、DataFrame列名など)に基づいてpandasオブジェクトを分割することを学びます.-カウント、平均、標準偏差、ユーザー定義関数などのグループ化要約統計を計算します.-DataFrameのカラムには、さまざまな関数が適用されます.-正規化、線形回帰、ランキング、サブセットの選択など、グループ内変換またはその他の演算を適用します.-ピボットまたはクロス集計を計算します.-ビット数分析およびその他のグループ分析を実行します.
パケット演算の最初のフェーズでは、pandasオブジェクト(Series、DataFrame、その他)のデータは、あなたが提供した1つ以上のキーに基づいて複数のグループに分割されます.分割操作は、オブジェクトの特定の軸で実行されます.例えば、DataFrameは、その行(axis=0)または列(axis=1)上でグループ化することができる.次に、関数を各パケットに適用し、新しい値を生成します.最後に、これらの関数の実行結果はすべて最終的な結果オブジェクトにマージされます.結果オブジェクトの形式は、一般に、データ上で実行される操作に依存します.図9〜図1は、単純なパケット集約プロセスを概略的に示す.
GroupByテクノロジー
グループ化キーには、さまざまな形式があり、同じタイプである必要はありません.
from pandas import Series,DataFrame
import pandas as pd
import numpy as np
df=DataFrame({'key1':['a','a','b','b','a'],'key2':['one','two','one','two','one'],
'data1':np.random.randn(5),'data2':np.random.randn(5)})
df
key 1でグループ化し、data 1列の平均値を計算します.data 1にアクセスし、key 1に基づいてgroupbyを呼び出すことができます.
grouped=df['data1'].groupby(df['key1'])
grouped
変数groupedはGroupByオブジェクトであり、次にGroupByのmeanメソッドを呼び出してパケット平均値を計算します.
grouped.mean()
key1
a 0.597727
b 0.318738
Name: data1, dtype: float64
複数の配列が一度に入力されると、異なる結果が得られます.
means=df['data1'].groupby([df['key1'],df['key2']]).mean()
means
key1 key2
a one 0.595071
two 0.603039
b one -0.077999
two 0.715474
Name: data1, dtype: float64
上から2つのキーでデータをグループ化したSeriesは階層化されたインデックス(一意のキーペアで構成されている)を持っており、次に置換する
means.unstack()
以上の例ではパケットキーはいずれもSeriesである.実際には、パケットキーは任意の長さの適切な配列であってもよい
states=np.array(['Ohio','California','California','Ohio','Ohio'])
years=np.array([2005,2005,2006,2005,2006])
states
array(['Ohio', 'California', 'California', 'Ohio', 'Ohio'],
dtype='
years
array([2005, 2005, 2006, 2005, 2006])
df['data1'].groupby([states,years]).mean()
California 2005 0.603039
2006 -0.077999
Ohio 2005 0.107602
2006 1.690412
Name: data1, dtype: float64
列名の文字列、数値、またはその他のPythonオブジェクトをグループ化キーとして使用できます.
df.groupby('key1').mean()
df.groupby(['key1','key2']).mean()
グループbyのsizeメソッドは、パケットサイズを含むSeriesを返すことができます.
df.groupby(['key1','key2']).size()
key1 key2
a one 2
two 1
b one 1
two 1
dtype: int64
グループの反復
groupbyオブジェクトは、グループ名とデータブロックからなる二元グループのセットを生成できます.
for name,group in df.groupby('key1'):
print(name)
print(group)
a
data1 data2 key1 key2
0 -0.500271 1.820004 a one
1 0.603039 -0.783806 a two
4 1.690412 -2.138761 a one
b
data1 data2 key1 key2
2 -0.077999 -1.464172 b one
3 0.715474 1.048138 b two
マルチキーの場合、メタグループの最初の要素はキー値からなるメタグループになります.
for (k1,k2),group in df.groupby(['key1','key2']):
print(k1,k2)
print(group)
a one
data1 data2 key1 key2
0 -0.500271 1.820004 a one
4 1.690412 -2.138761 a one
a two
data1 data2 key1 key2
1 0.603039 -0.783806 a two
b one
data1 data2 key1 key2
2 -0.077999 -1.464172 b one
b two
data1 data2 key1 key2
3 0.715474 1.048138 b two
これらのデータの断片を辞書にします
pieces=dict(list(df.groupby('key1')))
pieces
{'a': data1 data2 key1 key2
0 -0.500271 1.820004 a one
1 0.603039 -0.783806 a two
4 1.690412 -2.138761 a one, 'b': data1 data2 key1 key2
2 -0.077999 -1.464172 b one
3 0.715474 1.048138 b two}
pieces['b']
groupbyのデフォルトはaxis=0でグループ化され、次にdtypeに基づいてカラムをグループ化します.
df.dtypes
data1 float64
data2 float64
key1 object
key2 object
dtype: object
grouped=df.groupby(df.dtypes,axis=1)
dict(list(grouped))
{dtype('float64'): data1 data2
0 -0.500271 1.820004
1 0.603039 -0.783806
2 -0.077999 -1.464172
3 0.715474 1.048138
4 1.690412 -2.138761, dtype('O'): key1 key2
0 a one
1 a two
2 b one
3 b two
4 a one}
1つまたは複数の列の選択
DataFrameによって生成されたGroup Byオブジェクトに対して、1つの(単一文字列)または1つの(文字列配列)カラム名でインデックスを付けると、一部のカラムを集約する目的が達成されます.
df.groupby('key1')['data1']
df['data1'].groupby(df['key1'])
大きなデータセットの場合、一部のカラムを集約するだけで済みます.例えば、前のデータセットでは、data 2列の平均値を計算してデータFrame形式で結果を得るだけで、作成できます.
df.groupby(['key1','key2'])[['data2']].mean()
このインデックス操作で返されるオブジェクトは、リストまたは配列が入力された場合にパケット化されたDataFrameまたはパケット化されたSeries(スカラー形式の単一カラム名が入力された場合)です.
s_grouped=df.groupby(['key1','key2'])['data2']
s_grouped
s_grouped.mean()
key1 key2
a one -0.159378
two -0.783806
b one -1.464172
two 1.048138
Name: data2, dtype: float64
辞書またはSeriesによるグループ化
配列に加えて、パケット情報は他の形式で存在することもできます.例:DataFrame
people=DataFrame(np.random.randn(5,5),columns=['a','b','c','d','e'],
index=['Joe','Steve','Wes','Jim','Travis'])
people.loc[2:3,['b','c']]=np.nan # NA
people
既知のカラムのパケット関係を仮定し,パケットに基づいてカラムの合計を計算したい場合は,まずこの辞書をgroupbyに渡す.
mapping={'a':'red','b':'red','c':'blue','d':'blue','e':'red','f':'orange'}
by_column=people.groupby(mapping,axis=1)
by_column.sum()
Seriesにも同様の機能があり,固定サイズのマッピングと見なすことができる.この例では、Seriesをパケットキーとして使用すると、pandasはSeriesをチェックして、インデックスがパケット軸に整列していることを確認します.
map_series=Series(mapping)
map_series
a red
b red
c blue
d blue
e red
f orange
dtype: object
people.groupby(map_series,axis=1).count()
blue
red
Joe
2
3
Steve
2
3
Wes
1
2
Jim
2
3
Travis
2
3
関数によるグループ化
パケットキーとして使用される関数は、各インデックス値で1回呼び出され、その戻り値がパケット名として使用されます.
具体的には、上記の例であるDataFrameを例とし、そのインデックス値は人の名前である.人名の長さに基づいてグループ化したいと仮定すると、文字列の長さ配列を求めることができますが、len関数だけが入力されます.
people.groupby(len).sum()
関数を配列、リスト、辞書、Seriesと混合して使用できます.これは、最終的にはすべてのものが配列に変換されるためです.
key_list=['one','one','one','two','two']
people.groupby([len,key_list]).min()
インデックス・レベルでグループ化
階層化されたインデックス・データセットが最も便利なのは、インデックス・レベルに基づいて集約できることです.レベルキーによるレベル番号または名前の入力
columns=pd.MultiIndex.from_arrays([['US','US','US','JP','JP'],
[1,3,5,1,3]],names=['cty','tenor'])
hier_df=DataFrame(np.random.randn(4,5),columns=columns)
hier_df
hier_df.groupby(level='cty',axis=1).count()
データの集約
集約とは、配列からスカラー値を生成できる任意のデータ変換プロセスを指します.独自に発明された集約演算を使用して、パケット・オブジェクトで定義された任意の方法を呼び出すこともできます.
例えば、quantileは、SeriesまたはDataFrame列のサンプルビット数を計算することができる
df=DataFrame({'key1':['a','a','b','b','a'],'key2':['one','two','one','two','one'],
'data1':np.random.randn(5),'data2':np.random.randn(5)})
df
grouped=df.groupby('key1')
grouped['data1'].quantile(0.9)
key1
a -0.932423
b -0.006997
Name: data1, dtype: float64
独自の集約関数を使用する場合は、aggregateメソッドまたはaggメソッドに渡すだけです.
def peak_to_peak(arr):
return arr.max()-arr.min()
grouped.agg(peak_to_peak)
describeも使用できますが、厳密には集約演算ではありません.
grouped.describe()
data1 data2
key1
a count 3.000000 3.000000
mean 0.746672 0.910916
std 1.109736 0.712217
min -0.204708 0.092908
25% 0.137118 0.669671
50% 0.478943 1.246435
75% 1.222362 1.319920
max 1.965781 1.393406
b count 2.000000 2.000000
mean -0.537585 0.525384
std 0.025662 0.344556
min -0.555730 0.281746
25% -0.546657 0.403565
50% -0.537585 0.525384
75% -0.528512 0.647203
max -0.519439 0.769023
注:カスタム集約関数は、表9-1の最適化された関数よりもずっと遅いです.これは、中間パケットデータブロックを構築する際に非常に大きなオーバーヘッド(関数呼び出し、データ再配置など)が存在するためである
より高度な集約機能を説明するために、レストランのチップに関するデータセット(本書のGitHubライブラリ)を使用します.https://github.com/wesm/pydata-book/tree/1st-edition
read_経由csvロード後、チップの割合を表す列tip_を追加します.pct
tips=pd.read_csv('pydata_book/ch08/tips.csv') #
tips[:8] # 8
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
5 25.29 4.71 Male No Sun Dinner 4
6 8.77 2.00 Male No Sun Dinner 2
7 26.88 3.12 Male No Sun Dinner 4
tips['tip_pct']=tips['tip']/tips['total_bill'] # “ ”
tips[:8]
total_bill tip sex smoker day time size tip_pct
0 16.99 1.01 Female No Sun Dinner 2 0.059447
1 10.34 1.66 Male No Sun Dinner 3 0.160542
2 21.01 3.50 Male No Sun Dinner 3 0.166587
3 23.68 3.31 Male No Sun Dinner 2 0.139780
4 24.59 3.61 Female No Sun Dinner 4 0.146808
5 25.29 4.71 Male No Sun Dinner 4 0.186240
6 8.77 2.00 Male No Sun Dinner 2 0.228050
7 26.88 3.12 Male No Sun Dinner 4 0.116071
カラム向けマルチファンクションアプリケーション
Series列またはDataFrame列の集約演算は、実際にはaggregate(カスタム関数を使用)を使用するか、mean、stdなどの呼び出し方法であることが明らかになった.しかし、異なるカラムに対して異なる集約関数を使用するか、複数の関数を一度に適用したい場合があります.
次に、さまざまな例を練習します.
grouped=tips.groupby(['sex','smoker'])# sex smoker tips
grouped_pct=grouped['tip_pct'] #
grouped_pct.agg('mean')
sex smoker
Female No 0.156921
Yes 0.182150
Male No 0.160669
Yes 0.152771
Name: tip_pct, dtype: float64
関数または関数名のセットが入力されると、取得されたDataFrameの列は対応する関数で名前が付けられます.
grouped_pct.agg(['mean','std',peak_to_peak])
mean std peak_to_peak
sex smoker
Female No 0.156921 0.036421 0.195876
Yes 0.182150 0.071595 0.360233
Male No 0.160669 0.041849 0.220186
Yes 0.152771 0.090588 0.674707
入力された(name,function)メタグループからなるリストである場合、各メタグループの最初の要素はDataFrameのカラム名として使用されます(このようなメタグループリストは秩序マッピングと見なすことができます).
grouped_pct.agg([('foo','mean'),('bar',np.std)])
foo bar
sex smoker
Female No 0.156921 0.036421
Yes 0.182150 0.071595
Male No 0.160669 0.041849
Yes 0.152771 0.090588
DataFrameの場合、すべてのカラムに適用される関数のセットを定義するか、異なるカラムに異なる関数を適用します.tip_に対してpctとtotal_bill列計算の3つの統計
functions=['count','mean','max']
result=grouped['tip_pct','total_bill'].agg(functions)
result
結果DataFrameには階層化されたカラムがあります.これは、各カラムを集約し、concatで結果を統合することに相当します(カラム名はkeysパラメータとして使用されます).
result['tip_pct']
カスタム名付きメタグループのリストを入力
ftuples=[('Durchschnitt','mean'),('Abweichung',np.var)]
grouped['tip_pct','total_bill'].agg(ftuples)
異なるカラムに異なる関数を適用する場合.具体的にはaggにカラム名から関数にマッピングされた辞書を渡すことです
grouped.agg({'tip':np.max,'size':'sum'})
grouped.agg({'tip_pct':['min','max','mean','std'],'size':'sum'})
複数の関数を少なくとも1つのカラムに適用する場合にのみ、DataFrameは階層化されたカラムを持ちます.
集約データをインデックスなしで返す
例の集約データには、一意のグループ化キーからなるインデックス(階層化されている可能性があります)があります.必ずしもそうではないので、groupbyにas_を転送することができます.index=Falseこの機能を無効にする
結果に対してreset_を呼び出すindexもこのような形式の結果を得ることができます
tips.groupby(['sex','smoker'],as_index=False).mean()
次のセクションでは、パケットレベルの演算と変換を学習します.