Lewati ke konten utama

Frekuensi Absolut dan Berbobot Kata dalam Teks

Dalam tutorial ini, Anda akan mempelajari frekuensi kata absolut dan berbobot dalam text mining serta cara menghitungnya dengan defaultdict dan pandas DataFrame.
· 15 mnt Baca

Jelajahi bersama AI

Sekumpulan metrik penting dalam text mining berkaitan dengan frekuensi kemunculan kata (atau token apa pun) dalam suatu korpus dokumen teks. Namun, Anda juga dapat menggunakan metrik tambahan pada kasus di mana setiap dokumen memiliki nilai numerik terkait yang menjelaskan atribut tertentu dari dokumen tersebut.

Beberapa contohnya:

  • Tweet dan jumlah engagement masing-masing.
  • URL beserta pageview dan bounce-nya.
  • Judul film dan pendapatan kotor (gross revenue)-nya.
  • Kata kunci serta impresi, klik, dan konversinya.

Dalam tutorial ini,

  • Anda akan terlebih dahulu melalui proses membuat fungsi sederhana yang menghitung dan membandingkan kemunculan kata absolut dan tertimbang dalam sebuah korpus dokumen. Ini terkadang dapat mengungkap tren dan agregat tersembunyi yang tidak selalu terlihat jelas hanya dengan melihat sekitar sepuluh nilai teratas. Hasilnya juga sering berbeda dari frekuensi kata absolut.
  • Kemudian, Anda akan melihat set data nyata (judul film dan pendapatan kotor), dan berharap menemukan tren tersembunyi. Teaser: love bakal muncul entah bagaimana!
  • Anda akan menggunakan Python sebagai bahasa pemrograman dan memanfaatkan struktur data defaultdict dari modul collections untuk pekerjaan beratnya, serta DataFrame pandas untuk mengelola keluaran akhir.

Frekuensi Kata Absolut dan Tertimbang: Pengantar

Misalkan Anda memiliki dua tweet dengan konten dan jumlah impresi (tampilan) sebagai berikut:

Teks TweetTayangan
spain800
france200

Mudah untuk melakukan analisis dasar dan mengetahui bahwa kata Anda terbagi 50:50 antara 'france' dan 'spain'. Dalam banyak kasus, hanya ini yang Anda miliki, dan Anda hanya dapat mengukur frekuensi kata absolut, lalu mencoba menyimpulkan hubungan tertentu. Dalam kasus ini, Anda memiliki beberapa data tentang masing-masing dokumen.

Frekuensi tertimbang di sini jelas berbeda, dan bagiannya 80:20. Dengan kata lain, meskipun 'spain' dan 'france' masing-masing muncul sekali di tweet Anda, dari perspektif pembaca, yang pertama muncul 800 kali, sedangkan yang kedua muncul 200 kali. Perbedaannya besar!

Frekuensi Kata Sederhana menggunakan defaultdict

Sekarang pertimbangkan contoh yang sedikit lebih rumit untuk kumpulan dokumen serupa:

DokumenTayangan
france200
spain180
spain beaches170
france beaches160
spain best beaches160

Sekarang Anda melakukan loop pada dokumen, memecahnya menjadi kata-kata, dan menghitung kemunculan setiap kata:

 from collections import defaultdict

import pandas as pd

text_list = ['france', 'spain', 'spain beaches', 'france beaches', 'spain best beaches']

word_freq = defaultdict(int)

for text in text_list:
    for word in text.split():
        word_freq[word] += 1

pd.DataFrame.from_dict(word_freq, orient='index') \
.sort_values(0, ascending=False) \
.rename(columns={0: 'abs_freq'})
 abs_freq
spain3
beaches3
france2
best1

Pada loop di atas, baris pertama melakukan loop pada text_list satu per satu. Baris kedua (dalam setiap dokumen) melakukan loop pada kata-kata tiap item, dipisah dengan karakter spasi (yang bisa saja karakter lain ('-', ',', '_', dll.)).

Saat Anda mencoba menetapkan nilai ke word_freq[word] ada dua kemungkinan skenario:

  1. Key word ada: penetapan dilakukan (menambahkan satu)
  2. Key word tidak ada di word_freq, dalam hal ini defaultdict memanggil fungsi default yang ditetapkan saat pertama kali didefinisikan, yaitu int pada kasus ini.

Saat int dipanggil, ia mengembalikan nol. Sekarang key ada, nilainya nol, dan siap diberi tambahan 1 pada nilainya.

Walaupun kata teratas adalah 'france' pada tabel pertama, setelah menghitung semua kata dalam tiap dokumen kita dapat melihat bahwa 'spain' dan 'beaches' sama-sama menempati posisi pertama. Ini penting untuk mengungkap tren tersembunyi, terutama ketika daftar dokumen yang Anda tangani berjumlah puluhan, atau ratusan, bahkan ribuan.

Frekuensi Kata Tertimbang

Setelah Anda menghitung kemunculan tiap kata dalam korpus dokumen, Anda ingin melihat frekuensi tertimbangnya. Artinya, Anda ingin melihat berapa kali kata-kata tersebut terlihat oleh pembaca, dibandingkan berapa kali Anda menggunakannya.

Pada tabel pertama, frekuensi absolut kata terbagi rata antara 'spain' dan 'france', tetapi 'spain' jelas memiliki bobot jauh lebih besar, karena nilainya 800, dibandingkan 200 untuk 'france'.

Lalu bagaimana frekuensi kata tertimbang untuk tabel kedua yang sedikit lebih kompleks?

Mari kita cari tahu!

Anda dapat menggunakan kembali sebagian kode yang dipakai di atas, dengan beberapa tambahan:

 # default value is now a list with two ints
word_freq = defaultdict(lambda: [0, 0]) 

# the `views` column you had in the first DataFrame
num_list = [200, 180, 170, 160, 160]

# looping is now over both the text and the numbers
for text, num in zip(text_list, num_list): 
    for word in text.split(): 
        # same as before
        word_freq[word][0] += 1 
        # new line, incrementing the numeric value for each word
        word_freq[word][1] += num 

columns = {0: 'abs_freq', 1: 'wtd_freq'}

abs_wtd_df = pd.DataFrame.from_dict(word_freq, orient='index') \
             .rename(columns=columns) \
             .sort_values('wtd_freq', ascending=False) \
             .assign(rel_value=lambda df: df['wtd_freq'] / df['abs_freq']) \
            .round()

abs_wtd_df.style.background_gradient(low=0, high=.7, subset=['rel_value'])
 abs_freqwtd_freqrel_value
spain3510170
beaches3490163
france2360180
best1160160

Beberapa pengamatan:

  • Walaupun 'france' adalah frasa tertinggi secara keseluruhan, 'spain' dan 'beaches' tampak lebih menonjol ketika Anda menggunakan frekuensi tertimbang.
  • rel_value adalah pembagian sederhana untuk mendapatkan nilai per kemunculan setiap kata.
  • Melihat rel_value, Anda juga melihat bahwa meskipun 'france' cukup rendah pada metrik wtd_freq, ada potensi di sana, karena nilai per kemunculannya tinggi. Ini bisa menjadi petunjuk untuk meningkatkan cakupan konten tentang 'france', misalnya.

Anda mungkin juga ingin menambahkan metrik lain yang menunjukkan persentase dan persentase kumulatif dari tiap jenis frekuensi agar Anda mendapatkan perspektif lebih baik tentang berapa banyak kata yang membentuk porsi terbesar dari total, jika ada:

 abs_wtd_df.insert(1, 'abs_perc', value=abs_wtd_df['abs_freq'] / abs_wtd_df['abs_freq'].sum())
abs_wtd_df.insert(2, 'abs_perc_cum', abs_wtd_df['abs_perc'].cumsum())
abs_wtd_df.insert(4, 'wtd_freq_perc', abs_wtd_df['wtd_freq'] / abs_wtd_df['wtd_freq'].sum())
abs_wtd_df.insert(5, 'wtd_freq_perc_cum', abs_wtd_df['wtd_freq_perc'].cumsum())
abs_wtd_df.style.background_gradient(low=0, high=0.8)
 abs_freqabs_percabs_perc_cumwtd_freqwtd_freq_percwtd_freq_perc_cumrel_value
spain30.3333330.3333335100.3355260.335526170
beaches30.3333330.6666674900.3223680.657895163
france20.2222220.8888893600.2368420.894737180
best10.11111111600.1052631160

Masih banyak yang bisa dianalisis, dan dengan lebih banyak data Anda biasanya akan mendapat lebih banyak kejutan.

Lalu seperti apa penerapannya di dunia nyata dengan data sungguhan?

Anda akan melihat judul film, melihat kata-kata mana yang paling sering digunakan dalam judul —itulah frekuensi absolut—, dan kata-kata mana yang terkait dengan pendapatan terbesar, atau frekuensi tertimbang.

Boxoffice Mojo memiliki daftar lebih dari 15.000 film, beserta pendapatan kotor dan peringkatnya. Mulailah dengan melakukan scraping data menggunakan requests dan BeautifulSoup — Anda sudah dapat menjelajahi Boxoffice Mojo di sini jika ingin:

 
import requests
from bs4 import BeautifulSoup
 final_list = []

for i in range(1, 156):
    if not i%10:
        print(i)
    page = 'http://www.boxofficemojo.com/alltime/domestic.htm?page=' + str(i) + '&p=.htm'
    resp = requests.get(page)
    soup = BeautifulSoup(resp.text, 'lxml')
    # trial and error to get the exact positions
    table_data = [x.text for x in soup.select('tr td')[11:511]]  
    # put every 5 values in a row
    temp_list = [table_data[i:i+5] for i in range(0, len(table_data[:-4]), 5)] 
    for temp in temp_list:
        final_list.append(temp)
10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
boxoffice_df = pd.DataFrame.from_records(final_list)

boxoffice_df.head(10)
 01234
01Star Wars: The Force AwakensBV$936,662,2252015
12AvatarFox$760,507,6252009^
23Black PantherBV$681,084,1092018
34TitanicPar.$659,363,9441997^
45Jurassic WorldUni.$652,270,6252015
56Marvel's The AvengersBV$623,357,9102012
67Star Wars: The Last JediBV$620,181,3822017
78The Dark KnightWB$534,858,4442008^
89Rogue One: A Star Wars StoryBV$532,177,3242016
910Beauty and the Beast (2017)BV$504,014,1652017
boxoffice_df.tail(15)
 01234
1548515486The Dark HoursN/A$4232005
15486154872:22Magn.$4222017
1548715488State ParkAtl$4211988
1548815489The Magician (2010)Reg.$4062010
1548915490SkinlessPPF$4002014
1549015491CinemanovelsMont.$3982014
1549115492Hannah: Buddhism's Untold JourneyKL$3962016
1549215493Apartment 143Magn.$3832012
1549315494The MarshAll.$3362007
1549415495The ChambermaidFM$3152015
1549515496News From Planet MarsKL$3102016
1549615497Trojan WarWB$3091997
1549715498Lou! Journal infimeDistrib.$2872015
1549815499InterventionAll.$2792007
1549915500PlaybackMagn.$2642012

Anda akan melihat bahwa beberapa nilai numerik memiliki karakter khusus ($, , , dan ^), dan beberapa nilai sebenarnya adalah N/A. Jadi Anda perlu mengubahnya:

na_year_idx =  [i for i, x in enumerate(final_list) if x[4] == 'n/a'] # get the indexes of the 'n/a' values
new_years = [1998, 1999, 1960, 1973]  # got them by checking online

print(*[(i, x) for i, x in enumerate(final_list) if i in na_year_idx], sep='\n')
print('new year values:', new_years)
(8003, ['8004', 'Warner Bros. 75th Anniversary Film Festival', 'WB', '$741,855', 'n/a'])
(8148, ['8149', 'Hum Aapke Dil Mein Rahte Hain', 'Eros', '$668,678', 'n/a'])
(8197, ['8198', 'Purple Moon (Re-issue)', 'Mira.', '$640,945', 'n/a'])
(10469, ['10470', 'Amarcord', 'Jan.', '$125,493', 'n/a'])
new year values: [1998, 1999, 1960, 1973]
for na_year, new_year in zip(na_year_idx, new_years):
    final_list[na_year][4] = new_year
    print(final_list[na_year], new_year)
['8004', 'Warner Bros. 75th Anniversary Film Festival', 'WB', '$741,855', 1998] 1998
['8149', 'Hum Aapke Dil Mein Rahte Hain', 'Eros', '$668,678', 1999] 1999
['8198', 'Purple Moon (Re-issue)', 'Mira.', '$640,945', 1960] 1960
['10470', 'Amarcord', 'Jan.', '$125,493', 1973] 1973

Sekarang Anda mengubah list menjadi DataFrame pandas dengan menamai kolom menggunakan nama yang sesuai, dan mengonversinya ke tipe data yang Anda inginkan.

 import re
regex = '|'.join(['\$', ',', '\^'])

columns = ['rank', 'title', 'studio', 'lifetime_gross', 'year']

boxoffice_df = pd.DataFrame({
    'rank': [int(x[0]) for x in final_list],  # convert ranks to integers
    'title': [x[1] for x in final_list],  # get titles as is
    'studio': [x[2] for x in final_list],  # get studio names as is
    'lifetime_gross': [int(re.sub(regex, '', x[3])) for x in final_list],  # remove special characters and convert to integer
    'year': [int(re.sub(regex, '', str(x[4]))) for x in final_list],  # remove special characters and convert to integer
})
print('rows:', boxoffice_df.shape[0])
print('columns:', boxoffice_df.shape[1])
print('\ndata types:')
print(boxoffice_df.dtypes)
boxoffice_df.head(15)
rows: 15500
columns: 5

data types:
lifetime_gross     int64
rank               int64
studio            object
title             object
year               int64
dtype: object
 lifetime_grossrankstudiotitleyear
09366622251BVStar Wars: The Force Awakens2015
17605076252FoxAvatar2009
26810841093BVBlack Panther2018
36593639444Par.Titanic1997
46522706255Uni.Jurassic World2015
56233579106BVMarvel's The Avengers2012
66201813827BVStar Wars: The Last Jedi2017
75348584448WBThe Dark Knight2008
85321773249BVRogue One: A Star Wars Story2016
950401416510BVBeauty and the Beast (2017)2017
1048629556111BVFinding Dory2016
1147454467712FoxStar Wars: Episode I - The Phantom Menace1999
1246099800713FoxStar Wars1977
1345900586814BVAvengers: Age of Ultron2015
1444813909915WBThe Dark Knight Rises2012

Kata 'star' adalah salah satu yang teratas, karena muncul dalam lima dari lima belas film teratas, dan Anda juga tahu bahwa seri Star Wars memiliki lebih banyak film, beberapa di antaranya juga berada di peringkat atas.

Sekarang mari gunakan kode yang Anda kembangkan dan lihat bagaimana kinerjanya pada set data ini. Tidak ada yang baru pada kode di bawah, Anda hanya mengemas semuanya dalam satu fungsi:

 def word_frequency(text_list, num_list, sep=None):
    word_freq = defaultdict(lambda: [0, 0])

    for text, num in zip(text_list, num_list):
        for word in text.split(sep=sep): 
            word_freq[word][0] += 1 
            word_freq[word][1] += num

    columns = {0: 'abs_freq', 1: 'wtd_freq'}

    abs_wtd_df = (pd.DataFrame.from_dict(word_freq, orient='index')
                 .rename(columns=columns )
                 .sort_values('wtd_freq', ascending=False)
                 .assign(rel_value=lambda df: df['wtd_freq'] / df['abs_freq']).round())

    abs_wtd_df.insert(1, 'abs_perc', value=abs_wtd_df['abs_freq'] / abs_wtd_df['abs_freq'].sum())
    abs_wtd_df.insert(2, 'abs_perc_cum', abs_wtd_df['abs_perc'].cumsum())
    abs_wtd_df.insert(4, 'wtd_freq_perc', abs_wtd_df['wtd_freq'] / abs_wtd_df['wtd_freq'].sum())
    abs_wtd_df.insert(5, 'wtd_freq_perc_cum', abs_wtd_df['wtd_freq_perc'].cumsum())

    return abs_wtd_df
word_frequency(boxoffice_df['title'], boxoffice_df['lifetime_gross']).head()
 abs_freqabs_percabs_perc_cumwtd_freqwtd_freq_percwtd_freq_perc_cumrel_value
The30550.0687470.068747675183424980.0811670.08116722100930.0
the13100.0294790.098227329731008600.0396390.12080625170306.0
of13990.0314820.129709301805924670.0362820.15708721572975.0
and5450.0122640.141973121881138470.0146520.17173922363512.0
21580.0035560.14552990326730580.0108590.18259857168817.0

Tidak mengherankan, 'stop words' menempati posisi teratas, yang hampir sama untuk sebagian besar kumpulan dokumen. Anda juga mendapati duplikasi, di mana sebagian menggunakan huruf kapital dan sebagian tidak. Jadi ada dua hal jelas yang perlu ditangani:

  1. Hapus semua stop words: Anda dapat melakukannya dengan menambahkan parameter baru ke fungsi, dan menyuplai daftar stop word Anda sendiri.
  2. Tangani semua kata dalam huruf kecil untuk menghilangkan duplikasi

Berikut pembaruan sederhana pada fungsi (parameter baru rm_words, serta baris 6, 7, dan 8):

# words will be expanded
def word_frequency(text_list, num_list, sep=None, rm_words=('the', 'and', 'a')):  
    word_freq = defaultdict(lambda: [0, 0])

    for text, num in zip(text_list, num_list):
        for word in text.split(sep=sep): 
            # This should take care of ignoring the word if it's in the stop words
            if word.lower() in rm_words:  
                continue                  
            # .lower() makes sure we are not duplicating words
            word_freq[word.lower()][0] += 1  
            word_freq[word.lower()][1] += num

    columns = {0: 'abs_freq', 1: 'wtd_freq'}

    abs_wtd_df = (pd.DataFrame.from_dict(word_freq, orient='index')
                 .rename(columns=columns )
                 .sort_values('wtd_freq', ascending=False)
                 .assign(rel_value=lambda df: df['wtd_freq'] / df['abs_freq']).round())

    abs_wtd_df.insert(1, 'abs_perc', value=abs_wtd_df['abs_freq'] / abs_wtd_df['abs_freq'].sum())
    abs_wtd_df.insert(2, 'abs_perc_cum', abs_wtd_df['abs_perc'].cumsum())
    abs_wtd_df.insert(4, 'wtd_freq_perc', abs_wtd_df['wtd_freq'] / abs_wtd_df['wtd_freq'].sum())
    abs_wtd_df.insert(5, 'wtd_freq_perc_cum', abs_wtd_df['wtd_freq_perc'].cumsum())

    abs_wtd_df = abs_wtd_df.reset_index().rename(columns={'index': 'word'})

    return abs_wtd_df
from collections import defaultdict
word_freq_df =  word_frequency(boxoffice_df['title'], 
                               boxoffice_df['lifetime_gross'],
                               rm_words=['of','in', 'to', 'and', 'a', 'the', 
                                         'for', 'on', '&', 'is', 'at', 'it',
                                         'from', 'with'])



word_freq_df.head(15).style.bar(['abs_freq', 'wtd_freq', 'rel_value'],
                                               color='#60DDFF') # E6E9EB

 katafreq_abspersen_abskumulatif_persen_absfreq_bobotpersen_freq_bobotkumulatif_persen_freq_bobotnilai_rel
021580.004439450.0044394590326730580.01376340.01376345.71688e+07
1star450.00126440.0057038553746588190.008189530.02195291.19437e+08
2man1950.005479070.011182939670378540.00604470.02799762.03438e+07
3part410.001152010.012334932625797770.004971290.03296897.95751e+07
4movie1170.003287440.015622432160505570.004900390.03786932.74876e+07
53630.001770160.017392531975911930.004872270.04274155.07554e+07
6ii670.001882550.019275130777128830.00468960.04743114.5936e+07
7wars:60.0001685870.019443727574971550.004201680.05163284.59583e+08
8last1330.0037370.023180726702296510.004068710.05570152.00769e+07
9harry270.000758640.023939326113297140.003978960.05968059.67159e+07
10me1400.003933690.02787324593301280.003747360.06342791.75666e+07
11potter100.0002809780.02815423948114270.003649050.06707692.39481e+08
12black710.001994940.030148923723064670.003614760.07069173.34128e+07
13-490.001376790.031525723394848780.003564740.07425644.77446e+07
14story1070.003006460.034532222314375260.003400110.07765652.08546e+07

Mari kita lihat DataFrame yang sama diurutkan berdasarkan abs_freq:

(word_freq_df.sort_values('abs_freq', ascending=False)
 .head(15)
    .style.bar(['abs_freq', 'wtd_freq', 'rel_value'],
               color='#60DDFF'))

 katafreq_abspersen_abskumulatif_persen_absfreq_bobotpersen_freq_bobotkumulatif_persen_freq_bobotnilai_rel
26love2110.005928630.06954216042068850.002444380.1113997.60288e+06
2man1950.005479070.011182939670378540.00604470.02799762.03438e+07
24my1910.005366680.061899416295404980.002482980.1064788.53163e+06
15i1680.004720430.039252622034397860.003357450.0810141.31157e+07
021580.004439450.0044394590326730580.01376340.01376345.71688e+07
10me1400.003933690.02787324593301280.003747360.06342791.75666e+07
31life1340.00376510.076482215346477320.002338390.1232971.14526e+07
8last1330.0037370.023180726702296510.004068710.05570152.00769e+07
23you1260.003540320.056532717137588530.002611310.1039951.36013e+07
4movie1170.003287440.015622432160505570.004900390.03786932.74876e+07
14story1070.003006460.034532222314375260.003400110.07765652.08546e+07
33night1040.002922170.081455515239173600.002322040.1279461.46531e+07
19american930.002613090.047850518688541920.002847630.09325912.00952e+07
117girl900.00252880.1516448427716610.001284160.266639.36413e+06
16day870.002444510.041697121641987600.003297660.08431162.48758e+07

Sekarang mari memvisualisasikan untuk membandingkan keduanya dan melihat tren yang tersembunyi:

 import matplotlib.pyplot as plt
plt.figure(figsize=(20,8))
plt.subplot(1, 2, 1)

word_freq_df_abs = word_freq_df.sort_values('abs_freq', ascending=False).reset_index()

plt.barh(range(20),
         list(reversed(word_freq_df_abs['abs_freq'][:20])), color='#288FB7')
for i, word in enumerate(word_freq_df_abs['word'][:20]):
    plt.text(word_freq_df_abs['abs_freq'][i], 20-i-1, 
             s=str(i+1) + '. ' + word + ': '  + str(word_freq_df_abs['abs_freq'][i]),
             ha='right', va='center', fontsize=14, color='white', fontweight='bold')
plt.text(0.4, -1.1, s='Number of times the word was used in a movie title; out of 15500 movies.', fontsize=14)
plt.text(0.4, -1.8, s='Data: boxofficemojo.com Apr. 2018.   Feedback: @eliasdabbas', fontsize=14)


plt.vlines(range(0, 210, 10), -1, 20, colors='gray', alpha=0.1)
plt.hlines(range(0, 20, 2), 0, 210, colors='gray', alpha=0.1)
plt.yticks([])
plt.xticks([])
plt.title('Words Most Used in Movie Titles', fontsize=22, fontweight='bold')

# =============
plt.subplot(1, 2, 2)
# plt.axis('off')
plt.barh(range(20),
         list(reversed(word_freq_df['wtd_freq'][:20])), color='#288FB7')
for i, word in enumerate(word_freq_df['word'][:20]):
    plt.text(word_freq_df['wtd_freq'][i], 20-i-1, 
             s=str(i+1) + '. ' + word + ': ' + '$' + str(round(word_freq_df['wtd_freq'][i] / 1000_000_000, 2)) + 'b',
             ha='right', va='center', fontsize=14, color='white', fontweight='bold')
plt.text(0.4, -1.1, s='Alltime boxoffice revenue of all movies whos title contained the word. (Top word is "2") ', fontsize=14)
plt.text(0.4, -1.8, s='Data collection & methodology: http://bit.ly/word_freq', fontsize=14)

plt.vlines(range(0, 9_500_000_000, 500_000_000), -1, 20, colors='gray', alpha=0.1)
plt.hlines(range(0, 20, 2), 0, 10_000_000_000, colors='gray', alpha=0.1)
plt.xlim((-70_000_000, 9_500_000_000))
plt.yticks([])
plt.xticks([])
plt.title('Words Most Associated With Boxoffice Revenue', fontsize=22, fontweight='bold')
plt.tight_layout(pad=0.01)
plt.show()

data box office paling banyak kata

Tampaknya, setidaknya di benak produser dan penulis, cinta memang menaklukkan segalanya! Itu adalah kata yang paling sering digunakan di semua judul film. Namun, posisinya tidak setinggi itu jika dilihat dari frekuensi berbobot (pendapatan box office).

Dengan kata lain, jika Anda melihat semua judul film, kata 'love' adalah yang paling sering Anda temukan. Tetapi jika memperkirakan kata mana yang paling sering muncul di mata penonton (menggunakan pendapatan kotor sebagai metrik), maka '2', 'star', dan 'man' adalah yang paling banyak ditonton, atau terkait dengan pendapatan terbesar.

Untuk memperjelas: ini adalah perhitungan yang sangat sederhana. Saat Anda mengatakan bahwa frekuensi berbobot dari kata 'love' adalah 1.604.106.767, itu berarti jumlah pendapatan kotor sepanjang masa dari semua film yang judulnya memuat kata 'love' adalah sebesar itu.

Menarik juga bahwa '2' adalah kata teratas. Jelas, itu bukan kata, tetapi ini menunjukkan bahwa bagian kedua dari seri film menyumbang jumlah yang sangat besar. Begitu juga '3', yang berada di posisi kelima. Perhatikan bahwa 'part' dan 'ii' juga termasuk dalam sepuluh besar, yang menegaskan fakta yang sama.

'American' dan 'movie' memiliki nilai relatif yang tinggi.

Catatan singkat tentang stop word yang digunakan dalam fungsi ini

Biasanya, Anda akan menyediakan daftar stop word yang lebih komprehensif daripada yang ada di sini, terutama jika Anda berurusan dengan artikel atau unggahan media sosial. Misalnya paket nltk menyediakan daftar stop word dalam beberapa bahasa, yang dapat diunduh dan digunakan.

Kata-kata di sini dipilih setelah beberapa pemeriksaan pada film-film teratas. Banyak di antaranya biasanya dianggap sebagai stop word, tetapi dalam kasus judul film, masuk akal untuk mempertahankan sebagian karena bisa memberikan wawasan. Misalnya, kata 'I', 'me', 'you' bisa mengisyaratkan dinamika sosial tertentu. Alasan lain adalah judul film merupakan frasa yang sangat singkat, dan kita berusaha mendapatkan makna sebanyak mungkin darinya.

Anda tentu bisa mencobanya dengan himpunan kata milik Anda sendiri, dan melihat hasil yang sedikit berbeda.

Jika menengok kembali daftar judul film asli, kita melihat bahwa beberapa kata teratas bahkan tidak muncul dalam sepuluh besar, dan inilah tepatnya jenis wawasan yang ingin kita ungkap dengan pendekatan ini.

boxoffice_df.head(10)
 lifetime_grossrankstudiotitleyear
09366622251BVStar Wars: The Force Awakens2015
17605076252FoxAvatar2009
26810841093BVBlack Panther2018
36593639444Par.Titanic1997
46522706255Uni.Jurassic World2015
56233579106BVMarvel's The Avengers2012
66201813827BVStar Wars: The Last Jedi2017
75348584448WBThe Dark Knight2008
85321773249BVRogue One: A Star Wars Story2016
950401416510BVBeauty and the Beast (2017)2017

Selanjutnya, menurut saya masuk akal untuk mengeksplorasi lebih jauh kata-kata teratas yang menarik. Mari memfilter film yang memuat '2' dan lihat:

(boxoffice_df[boxoffice_df['title']                  
              .str
              .contains('2 | 2', case=False)] # spaces used to exclude words like '2010'
              .head(10))
 lifetime_grossrankstudiotitleyear
1544122624716DWShrek 22004
3038981310131BVGuardians of the Galaxy Vol. 22017
3138101121932WBHarry Potter and the Deathly Hallows Part 22011
3537358582536SonySpider-Man 22004
3836806126539Uni.Despicable Me 22013
6431243333165Par.Iron Man 22010
7929232473780LG/SThe Twilight Saga: Breaking Dawn Part 22012
8728172390288LGFThe Hunger Games: Mockingjay - Part 22015
117245852179118BVToy Story 21999
146226164286147NLRush Hour 22001

Mari juga intip film 'star' teratas:

boxoffice_df[boxoffice_df['title'].str.contains('star | star', case=False)].head(10)
 lifetime_grossrankstudiotitleyear
09366622251BVStar Wars: The Force Awakens2015
66201813827BVStar Wars: The Last Jedi2017
85321773249BVRogue One: A Star Wars Story2016
1147454467712FoxStar Wars: Episode I - The Phantom Menace1999
1246099800713FoxStar Wars1977
3338027057734FoxStar Wars: Episode III - Revenge of the Sith2005
6531067674066FoxStar Wars: Episode II - Attack of the Clones2002
105257730019106Par.Star Trek2009
140228778661141Par.Star Trek Into Darkness2013
301158848340302Par.Star Trek Beyond2016

Dan terakhir, film 'man' teratas:

boxoffice_df[boxoffice_df['title'].str.contains('man | man', case=False)].head(10)
 lifetime_grossrankstudiotitleyear
1842331581219BVPirates of the Caribbean: Dead Man's Chest2006
2240901399423BVIron Man 32013
3537358582536SonySpider-Man 22004
4833653030349SonySpider-Man 32007
5333036019454WBBatman v Superman: Dawn of Justice2016
5931841210160Par.Iron Man2008
6431243333165Par.Iron Man 22010
8229104551883WBMan of Steel2013
176206852432177WBBatman Begins2005
182202853933183SonyThe Amazing Spider-Man 22014

Langkah Selanjutnya dan Peningkatan

Sebagai langkah awal, Anda bisa mencoba mendapatkan lebih banyak kata: judul film sangat pendek dan sering kali tidak menyampaikan makna harfiahnya. Misalnya, godfather seharusnya adalah orang yang menjadi saksi pembaptisan seorang anak dan berjanji untuk merawat anak tersebut (atau mungkin seorang mafia yang membunuh demi kesenangan?!).

Latihan lanjutan bisa berupa memperoleh deskripsi yang lebih terperinci, selain judul film. Misalnya:

"Seorang peretas komputer belajar dari pemberontak misterius tentang hakikat sebenarnya dari realitasnya dan perannya dalam perang melawan para pengendali."

memberi kita informasi jauh lebih banyak tentang film tersebut dibandingkan 'The Matrix'.

Alternatifnya, Anda juga dapat menempuh salah satu jalur di bawah ini untuk memperkaya analisis Anda:

  • Analisis statistik yang lebih baik: menangani nilai ekstrem/outlier, menggunakan metrik lain.
  • Text mining: mengelompokkan kata dan topik serupa ('happy', 'happiness', 'happily', dll.)
  • Analisis granular: menjalankan fungsi yang sama untuk tahun/dekade berbeda, atau untuk studio produksi tertentu.

Anda mungkin tertarik mengeksplorasi data ini sendiri serta data lainnya:

Baik, sekarang Anda telah menelusuri hitungan kata dalam judul film, dan melihat perbedaan antara frekuensi absolut dan berbobot, serta bagaimana mengabaikan salah satunya bisa membuat Anda kehilangan sebagian besar gambaran. Anda juga telah melihat keterbatasan pendekatan ini, dan memiliki beberapa saran untuk meningkatkan analisis Anda.

Anda telah melalui proses membuat fungsi khusus yang bisa dijalankan dengan mudah untuk menganalisis himpunan data teks serupa dengan angka, dan mengetahui bagaimana hal ini dapat meningkatkan pemahaman Anda tentang jenis data tersebut.

Cobalah dengan menganalisis performa tweet Anda, URL situs web Anda, postingan Facebook Anda, atau himpunan data serupa lainnya yang mungkin Anda temui.

Mungkin lebih mudah untuk langsung mengkloning repositori beserta kodenya dan mencobanya sendiri.

Fungsi word_frequency adalah bagian dari paket advertools, yang dapat Anda unduh dan coba gunakan dalam pekerjaan/riset Anda.

Coba lihat dan beri tahu saya! @eliasdabbas

Lihat Tutorial Python Dictionaries dari DataCamp untuk mempelajari cara membuat frekuensi kata, dan tutorial Web Scraping & NLP di Python untuk mempelajari cara memplot distribusi frekuensi kata.

Topik

Terkait

blogs

Tutorial Korelasi di R

blogs

Spaghetti Plot dan Jalur Badai