Calcular el porcentaje de valores similares en el marco de datos de pandas

14

Tengo un marco de datos df, con dos columnas: Script (con texto) y Speaker

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

Y tengo la siguiente lista: L = ['a','b','c']

Con el siguiente código,

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

Obtengo este marco de datos df2:

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

¿Qué línea puedo agregar en mi código para obtener, para cada línea de mi marco de datos df2, un valor porcentual de todas las líneas pronunciadas por el hablante, para tener el siguiente marco de datos df3:

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

Respuestas:

8

Puede dividir por a lo sumlargo del primer eje y luego convertir a cadena y agregar %:

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%
yatu
fuente
5

A partir de su marco de datos original, si desea% y no la suma de dummies agrupados, puede cambiar el script completo de la siguiente manera:

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

Si no quieres el porcentaje solo usa:

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: esto usa pandas 0.25+ como versión

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

Salida:

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
Quang Hoang
fuente
2

Dado el ejemplo, puede probar con la siguiente línea de código:

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

Con los datos que proporciona:

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)

Salida:

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

O, si desea agregar el símbolo '%':

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

Salida:

      a     b    c
0   50%   25%  25%
1  100%    0%   0%
2    0%  100%   0%
Celius Stingher
fuente