2013-03-13 10 views
18

my_labelsという列のパンダデータフレームがあり、文字列には'A', 'B', 'C', 'D', 'E'が含まれています。私はこれらの文字列のそれぞれの出現の数を数えたいと思って、数の数をすべての数の合計で割ります。私はこのようなパンダでこれをやろうとしている:パンダグループに機能を適用

func = lambda x: x.size()/x.sum() 
data = frame.groupby('my_labels').apply(func) 

このコードは、エラーをスローし、サイズ 『「データフレームのオブジェクトには属性がありません』。パンダでこれを計算する関数をどのように適用できますか?

答えて

21

applyは、に適用され、それぞれの値ではなく、という値であり、kwargsを受け入れます。 したがって、値には.size()メソッドがありません。

おそらく、これは動作します:

from pandas import * 

d = {"my_label": Series(['A','B','A','C','D','D','E'])} 
df = DataFrame(d) 


def as_perc(value, total): 
    return value/float(total) 

def get_count(values): 
    return len(values) 

grouped_count = df.groupby("my_label").my_label.agg(get_count) 
data = grouped_count.apply(as_perc, total=df.my_label.count()) 

をここ.agg()方法はgroupby objectすべて値に適用される関数を取ります。

6

試してみてください。

g = pd.DataFrame(['A','B','A','C','D','D','E']) 

# Group by the contents of column 0 
gg = g.groupby(0) 

# Create a DataFrame with the counts of each letter 
histo = gg.apply(lambda x: x.count()) 

# Add a new column that is the count/total number of elements  
histo[1] = histo.astype(np.float)/len(g) 

print histo 

出力:

0   1 
0    
A 2 0.285714 
B 1 0.142857 
C 1 0.142857 
D 2 0.285714 
E 1 0.142857 
+1

です – Reservedegotist

1

私はS.O.上の加重平均を計算するために、ネストされた機能の技術を見てその技術を変えることで、あなたの問題を解決することができます。ここで

def group_weight(overall_size): 
    def inner(group): 
     return len(group)/float(overall_size) 
    inner.__name__ = 'weight' 
    return inner 

d = {"my_label": pd.Series(['A','B','A','C','D','D','E'])} 
df = pd.DataFrame(d) 
print df.groupby('my_label').apply(group_weight(len(df))) 



my_label 
A 0.285714 
B 0.142857 
C 0.142857 
D 0.285714 
E 0.142857 
dtype: float64 

グループ内

def wavg(val_col_name,wt_col_name): 
    def inner(group): 
     return (group[val_col_name] * group[wt_col_name]).sum()/group[wt_col_name].sum() 
    inner.__name__ = 'wgt_avg' 
    return inner 



d = {"P": pd.Series(['A','B','A','C','D','D','E']) 
    ,"Q": pd.Series([1,2,3,4,5,6,7]) 
    ,"R": pd.Series([0.1,0.2,0.3,0.4,0.5,0.6,0.7]) 
    } 

df = pd.DataFrame(d) 
print df.groupby('P').apply(wavg('Q','R')) 

P 
A 2.500000 
B 2.000000 
C 4.000000 
D 5.545455 
E 7.000000 
dtype: float64 
0

Starting with Pandas version 0.22を加重平均を行うには、applyの代替も存在する方法である:(あなたもthis questionを確認することができますpipeapplyを使用するよりもかなり高速になります2つの機能の間の相違点については、ご例えば

df = pd.DataFrame({"my_label": ['A','B','A','C','D','D','E']}) 

    my_label 
0  A 
1  B 
2  A 
3  C 
4  D 
5  D 
6  E 

applyバージョン

df.groupby('my_label').apply(lambda grp: grp.count()/df.shape[0]) 

  my_label 
my_label   
A   0.285714 
B   0.142857 
C   0.142857 
D   0.285714 
E   0.142857 

pipeバージョン

を与える
df.groupby('my_label').pipe(lambda grp: grp.size()/grp.size().sum()) 

利回り

my_label 
A 0.285714 
B 0.142857 
C 0.142857 
D 0.285714 
E 0.142857 

だから値がしかし、タイミングが(少なくとも、この小さなデータフレームのために)非常に多くの異なる、同じです:

%timeit df.groupby('my_label').apply(lambda grp: grp.count()/df.shape[0]) 
100 loops, best of 3: 5.52 ms per loop 

%timeit df.groupby('my_label').pipe(lambda grp: grp.size()/grp.size().sum()) 
1000 loops, best of 3: 843 µs per loop 

それを関数にラップすることもまた簡単です:

def get_perc(grp_obj): 
    gr_size = grp_obj.size() 
    return gr_size/gr_size.sum() 

今、あなたはしかし、この特定のケースのために、あなたもgroupbyを必要としない、しかし、あなたはちょうどこのようvalue_countsを使用することができます

my_label 
A 0.285714 
B 0.142857 
C 0.142857 
D 0.285714 
E 0.142857 

を得

df.groupby('my_label').pipe(get_perc) 

を呼び出すことができます。

df['my_label'].value_counts(sort=False)/df.shape[0] 

この小さなデータフレームのために
A 0.285714 
C 0.142857 
B 0.142857 
E 0.142857 
D 0.285714 
Name: my_label, dtype: float64 

それはあなたにも簡単にするために `ヒスト= gg.sizeを()`を使用することができ、非常に高速

%timeit df['my_label'].value_counts(sort=False)/df.shape[0] 
1000 loops, best of 3: 770 µs per loop 
関連する問題