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

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%

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


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

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%
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.