2017-06-28 6 views
4

Je cet objectif appelé dataframe:Python/Pandas - Performance - Calcul% de l'incidence d'une valeur dans une colonne

target: 

      group 
170 64.22-1-00 
72 64.22-1-00 
121 35.12-3-00 
99 64.22-1-00 
19 35.12-3-00 

Je veux créer une nouvelle colonne appelée group_incidence qui est le rapport de la fréquence que le groupe apparaît dans la base de données. Il est calculé comme suit:

[total number of times that that 'group' appeared in the group column]/len(target.index) 

Il ressemblerait à ceci:

  group group_incidence 
170 64.22-1-00    0.6 
72 64.22-1-00    0.6 
121 35.12-3-00    0.4 
99 64.22-1-00    0.6 
19 35.12-3-00    0.4 

j'ai pu le faire à travers une boucle for, cependant, puisque c'est un grand dataframe, il prend trop de temps. Je crois que si je pouvais passer la boucle for, j'aurais des gains de performance considérables.

Existe-t-il un moyen d'effectuer la même opération sans passer par la boucle for?

Répondre

4
In [112]: df['group_incidence'] = df.groupby('group')['group'].transform('size')/len(df)  

In [113]: df 
Out[113]: 
      group group_incidence 
170 64.22-1-00    0.6 
72 64.22-1-00    0.6 
121 35.12-3-00    0.4 
99 64.22-1-00    0.6 
19 35.12-3-00    0.4 
+3

Aurait 'len (df) 'outside' applique' peut-être? 'df.groupby ('groupe') ['group']. transform ('count')/len (df)' – Zero

+0

@JohnGalt, très bon point, merci! – MaxU

4

Approche # 1

Une approche NumPy serait -

_,tags, c = np.unique(df.group.values, return_counts=1, return_inverse=1) 
df['group_incidence'] = (c/c.sum())[tags] 

run échantillon -

In [584]: df 
Out[584]: 
      group 
170 64.22-1-00 
72 64.22-1-00 
121 35.12-3-00 
99 64.22-1-00 
19 35.12-3-00 

In [585]: _,tags, c = np.unique(df.group.values, return_counts=1, return_inverse=1) 

In [586]: df['group_incidence'] = (c/c.sum())[tags] 

In [587]: df 
Out[587]: 
      group group_incidence 
170 64.22-1-00    0.6 
72 64.22-1-00    0.6 
121 35.12-3-00    0.4 
99 64.22-1-00    0.6 
19 35.12-3-00    0.4 

Approche # 2

autre avec un peu de désordre/bas niveau NumPy tweaks avec l'idée d'obtenir des performances -

def argsort_unique(idx): 
    # Original idea : http://stackoverflow.com/a/41242285/3293881 by @Andras 
    n = idx.size 
    sidx = np.empty(n,dtype=int) 
    sidx[idx] = np.arange(n) 
    return sidx 

def group_ratios_tagged(a): 
    sidx = a.argsort() 
    b = a[sidx] 

    m = np.concatenate(([False], b[1:] != b[:-1])) 
    sep_idx = np.concatenate(([0], np.flatnonzero(m), [a.size])) 
    idx = m.astype(int) 
    np.maximum.accumulate(idx, out=idx) 

    c = sep_idx[1:] - sep_idx[:-1] 
    h = (c/c.sum())[idx] 
    out = h[argsort_unique(sidx)] 
    return out 

run échantillon (comment utiliser) -

In [659]: df = pd.read_clipboard() 

In [660]: df 
Out[660]: 
      group 
170 64.22-1-00 
72 64.22-1-00 
121 35.12-3-00 
99 64.22-1-00 
19 35.12-3-00 

In [661]: df['group_incidence'] = group_ratios_tagged(df.group.values) 

In [662]: df 
Out[662]: 
      group group_incidence 
170 64.22-1-00    0.6 
72 64.22-1-00    0.6 
121 35.12-3-00    0.4 
99 64.22-1-00    0.6 
19 35.12-3-00    0.4