Calcola la percentuale di valori simili nel frame di dati di Panda


14

Ho un frame di dati df, con due colonne: Script (con testo) e Speaker

Script  Speaker
aze     Speaker 1 
art     Speaker 2
ghb     Speaker 3
jka     Speaker 1
tyc     Speaker 1
avv     Speaker 2 
bhj     Speaker 1

E ho il seguente elenco: L = ['a','b','c']

Con il seguente codice,

df = (df.set_index('Speaker')['Script'].str.findall('|'.join(L))
        .str.join('|')
        .str.get_dummies()
        .sum(level=0))
print (df)

Ottengo questo frame di dati df2:

Speaker     a    b    c
Speaker 1   2    1    1
Speaker 2   2    0    0
Speaker 3   0    1    0

Quale riga posso aggiungere nel mio codice per ottenere, per ogni riga del mio frame di dati df2, un valore percentuale di tutte le righe pronunciate dal relatore, al fine di avere il seguente frame di dati df3:

Speaker     a    b    c
Speaker 1   50%  25%   25%
Speaker 2  100%    0   0
Speaker 3   0   100%   0

Risposte:


8

È possibile dividere per il sumprimo asse, quindi eseguire il cast su stringa e aggiungere %:

out = (df.set_index('Speaker')['Script'].str.findall('|'.join(L))
         .str.join('|')
         .str.get_dummies()
         .sum(level=0))

(out/out.sum(0)[:,None]).mul(100).astype(int).astype(str).add('%')

            a     b    c
Speaker                  
Speaker1   50%   25%  25%
Speaker2  100%    0%   0%
Speaker3    0%  100%   0%

5

A partire dal tuo frame di dati originale, se vuoi la somma di manichini% e non raggruppata, puoi modificare l'intero script come di seguito:

m = df.set_index('Speaker')['Script'].str.findall('|'.join(L)) #creates a list of matches
m = m.explode().reset_index() #explode to a series 
final = pd.crosstab(m['Speaker'],m['Script'],normalize='index').mul(100) # percentage pivot

Script         a      b     c
Speaker                      
Speaker 1   50.0   25.0  25.0
Speaker 2  100.0    0.0   0.0
Speaker 3    0.0  100.0   0.0

Se non vuoi la percentuale, usa solo:

pd.crosstab(m['Speaker'],m['Script'])

Script     a  b  c
Speaker           
Speaker 1  2  1  1
Speaker 2  2  0  0
Speaker 3  0  1  0

Nota: questo utilizza i panda 0.25+ come versione


3
(df.set_index('Speaker')['Script'].str.extractall(f'({"|".join(L)})')
   .groupby('Speaker')[0].value_counts(normalize=True)
   .unstack(fill_value=0)
)

Produzione:

0            a     b     c
Speaker                   
Speaker 1  0.5  0.25  0.25
Speaker 2  1.0  0.00  0.00
Speaker 3  0.0  1.00  0.00

2

Dato l'esempio puoi provare con la seguente riga di codice:

df = (df/df.sum(axis=1)[:, None]).mul(100).astype(int)

Con i dati forniti:

import pandas as pd
import numpy as np
data = {'a':[2,2,0],'b':[1,0,1],'c':[1,0,0]}
df = pd.DataFrame(data)
df = (df/df.sum(axis=1)[:, None]).mul(100).astype(int)
print(df)

Produzione:

     a   b   c
0   50  25  25
1  100   0   0
2    0 100   0

Oppure, se si desidera aggiungere il simbolo '%':

df = (df / df.sum(axis=1)[:, None]).mul(100).astype(int).astype(str) + '%'

Produzione:

      a     b    c
0   50%   25%  25%
1  100%    0%   0%
2    0%  100%   0%
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.