Hitung persentase nilai yang sama dalam bingkai data panda

14

Saya memiliki satu kerangka data df, dengan dua kolom: Script (dengan teks) dan Speaker

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

Dan saya memiliki daftar berikut: L = ['a','b','c']

Dengan kode berikut,

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

Saya mendapatkan kerangka data ini df2:

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

Baris mana yang dapat saya tambahkan dalam kode saya untuk mendapatkan, untuk setiap baris kerangka data saya df2, nilai persentase dari semua baris yang diucapkan oleh pembicara, untuk memiliki kerangka data berikut df3:

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

Jawaban:

8

Anda bisa membaginya sumsepanjang sumbu pertama dan kemudian melemparkannya ke string dan menambahkan %:

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
sumber
5

Mulai dari kerangka data asli Anda, jika Anda ingin% dan tidak mengelompokkan jumlah boneka, Anda dapat mengubah seluruh skrip seperti di bawah ini:

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

Jika Anda tidak ingin persentasenya gunakan saja:

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

Catatan: ini menggunakan panda 0.25+ sebagai versi

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

Keluaran:

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
sumber
2

Diberikan contoh, Anda dapat mencoba dengan baris kode berikut:

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

Dengan data yang Anda berikan:

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)

Keluaran:

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

Atau, jika Anda ingin menambahkan simbol '%':

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

Keluaran:

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