Text PreProcessing & Terms Distribution

Artikel ini merupakan lanjutan dari artikel sebelumnya tentang Crawling Data Twitter dengan Python. Akan tetapi apa yang dijelaskan di artikel ini dapat diterapkan di sembarang data text/dokumen, tidak harus data sosial media. Preprocessing text seperti stopword filtering & stemming, serta menghitung term distribution (frekuensi kata) dibahas menggunakan Python. Di tulisan selanjutnya kita akan coba melakukan analisa lanjut seperti clustering, centrality, community detection, visualisasi, dsb.

Apa yang akan dibahas di artikel ini?

  • Preprocessing sederhana text data di Python: StopWords, Regular Expression “sederhana”, stemming, dsb.
  • Read dan Write data ke sebuah file di Python.
  • list comprehensions dan beberapa struktur data sederhana di Python (dictionary, list, & set).
  • Indikator progress code di Python dengan tqdm.

Pendahuluan

  1. Amat disarankan untuk menjalankan terlebih dahulu program di artikel sebelumnya untuk mendapatkan data twitter anda sendiri. Berarti saya juga mengasumsikan Python, dan modul-modul di artikel tersebut telah terinstall dengan baik.
  2. Saya mengasumsikan pembaca tidak “Phobia”/takut/antipati terhadap bahasa pemrograman (khususnya Python). Bagi pembaca yang ingin mempelajari Python, tutorial berikut menurut saya amat baik untuk pemula.
  3. Di artikel ini kita akan menggunakan beberapa modul baru: json, re, nltk, collections, dan tqdm. Seperti di artikel sebelumnya, menginstall modul-modul tersebut sangatlah mudah, di terminal (shell/command prompt) cukup ketikkan perintah-perintah berikut:
    *catatan: kalau anda menggunakan Anaconda, kemungkinan besar json, re, collections, dan nltk sudah terinstall. Jika tidak lakukan hal yang sama seperti perintah di atas: “pip install namaModul
  4. Source code, StopWords, dan contoh data artikel ini dapat diunduh disini: ~LINK~ Di file tersebut saya melampirkan contoh >22.000 data tweet “@RidwanKamil”  pada tanggal 28 Nov~29 Des 2015.
  5. Saya menggunakan 3 macam StopWords di code yang akan kita bahas: Inggris, Indonesia, dan tambahan khusus dari user (variabel SpecialStopWords). Stopwords lain seperti bahasa daerah (e.g. bahasa sunda:{jeung, kang, oge,…}) dapat ditambahkan sendiri dengan cara seperti yang ada dalam codenya. Kalau menemukan kesulitan, silahkan komentar dibawah (jangan lupa lampirkan juga pesan error yg muncul).

Let’s get started!

First thing first, berikut adalah code seutuhnya, pembahasan/keterangan code ada dibawahnya. Silahkan buka code ini di editor Python anda (misal Spyder).

  1. Baris ke 1-4: import moduls
    Import fungsi-fungsi (modul) yang akan kita butuhkan. Jika ada error di 4 baris ini berarti modul belum terinstall atau ‘rusak’. Jangan hawatir solusinya cukup lakukan jalankan point 3 di Pendahuluan. Perhatikan modul tqdm memiliki perintah yang import yang unik dan berbeda dengan modul lainnya.
  2. Baris ke 6-10: data & file names
    Saya mengasumsikan data dan hasil program diatas diletakkan di folder “data” dengan nama-nama file yang telah ditetapkan di baris ke 6-10 di code ini. Backslash ditulis dua kali (\\) karena di Python “\” memiliki makna khusus.
    _
    Saat crawling saya menggunakan keywords ‘ridwankamil’, ‘ridwan’, dan ‘kamil’, sehingga wajar jika saya asumsikan kata-kata tersebut sebagai stopwords juga. Silahkan tambahkan/kurangi sesuai selera … :)  … file “StopWords_Eng-Ind.txt” berisi gabungan stopwords bahasa Indonesia & Inggris.
  3. Baris 12-18:  Fungsi wordCount
    Fungsi memliki input sebuah text (dTxt) yang akan dihitung kata-katanya serta 3 buah variable (dictionary) yang akan digunakan untuk menyimpan hasil perhitungan kata: wID,fD,fT.
    _
    Dictionarynya memiliki kunci string (terms/kata) dan nilai/value berupa integer. wID akan sangat bermanfaat kelak saat kita akan melakukan analisa lebih lanjut seperti clustering, karena kita memerlukan VSM (vector space model) sebagai data representation textnya (let’s not worry about that for now).
    _
    Contoh wID[‘walikota’]=33 artinya adalah kata ‘walikota’ memiliki kata ID 33. fD[‘walikota’] menyimpan jumlah tweet yang memuat kata ‘walikota’, dan fT[‘walikota’] menyimpan total jumlah kata walikota di corpus (dataset). Perhatikan fD╪fT karena sebuah tweet bisa memuat kata yang sama berkali-kali. fD dan fT kelak juga akan bermanfaat ketika akan melakukan analisis statistik tingkat lanjut data teks kita.
  4. Baris 20-25: Fungsi WriteWordStat
    Fungsi akan menyimpan term distribusi hasil perhitungannya.
  5. Baris 27-35: Load StopWords & inisialisasi
    Baris 33-35 me-load stopwords dan menggabungkannya. Penting untuk merubah list stopwordsnya ke tipe data “set” di python untuk mempercepat performa dan menghindari duplikasi.
  6. Baris 36-49: Proses Inti
    Baris 36 adalah reguler expression untuk mendapatkan hanya huruf dan angka saja dari data kita (alphanumeric). Reguler expression (regex) amat-amat-amat penting bagi mereka yang berkecimpung dengan data teks. Silahkan baca lebih lanjut disini jika ingin mendalaminya lebih jauh.
    _
    Baris 38 membuka (menyiapkan) file untuk menyimpan hasil preprocessing.
    Baris 40 me-load semua data tweet kita ke memory.
    _
    Baris 42 menggunakan modul tqdm untuk membuat progress bar (indikator).
    Baris 43 meyakinkan agar kalau ada data yang ‘corrupt’ prosesnya tidak perlu berhenti, namun cukup mengabaikan saja data tweet tersebut.
    Baris 44 merubah data tweet kita yang berbentuk string kembali ke bentuk json seperti data yang dikirimkan dari web twitter.
    Baris 45 merubah data tweet menjadi lowercase.
    Baris 46 menghapus semua URL (alamat internet) dari tweet menggunakan Regex, karena akan mengganggu analisa.
    Baris 47 merubah tweet menjadi bentuk alphanumeriknya, sehingga semua simbol akan hilang.
    Baris 50 menggabungkan kata-kata yang ada kembali menjadi kalimat utuh.
    Baris 51 menyimpannya ke file.
    Baris ke 52 menghitung term statistics/distribution.
  7. Baris 51-56: Wrap Up
    Baris-baris ini adalah perintah yang digunakan untuk mengurutkan term statisticnya. Distribusi kata diurutkan berdasarkan frekuensi kemunculan pada tweet yang paling banyak (fD).

Done!!!… seperti biasa, programnya dapat dijalankan dengan menekan tombol “F5” di Spyder atau jalankan melalui command prompt (shell/terminal) dengan perintah berikut:

Silahkan lihat hasilnya di folder “data”.

Stemming

wait a minute,… mana stemmingnya? …. sengaja saya tidak tuliskan di code diatas. Karena stemming biasanya optional dan computationally expensive.  Untuk menambahkan proses  stemming, tambahkan code berikut:

“CoPas” baris satu ke baris 11 di code diatas dan baris ke dua diantara baris 48 dan 49.  Notes, bahwa terdapat berbagai macam stemming di NLTK. Silahkan baca lebih lanjut disini. Stemming bahasa Indonesia dan bahasa daerah juga bisa ditambahkan dengan cara yang kurang lebih sama.

Batasan/Limitations:

  • Kalau anda melihat hasil preprocess-nya akan terlihat beberapa tweet duplicate. Hal tersebut kemungkinan besar akibat user yang melakukan retweet. Saya sengaja tidak menghilangkan duplikasinya untuk menghindari kompleksitas artikel dan membuat tweet tertentu memiliki ‘bobot’ yang berbeda. Menghilangkan duplikasi tersebut di Python amat sederhana dan cukup cepat. Cukup dengan menyimpan variabel “cleanTweet” ke dalam struktur data “set” di python.
  • Bergantung dari data twitter seperti apa yang anda crawl, mungkin stopwords tambahan juga diperlukan, misal StopWords bahasa Sunda atau bahasa alay/gaul
  • Begitu juga dengan proses stemmingnya: stemming bahasa Indonesia, Sunda, dan bahasa gaul/alay.
  • Codenya bisa lebih cepat dengan membuat variabel-variabel Terms Statistics menjadi “global” di fungsi “wordCount”. Sengaja saya tidak lakukan untuk menekankan bahwa artikel ini untuk pemula. Untuk data ‘hanya’ beberapa gigabyte tidak perlu hawatir, code diatas cukup cepat (thanks to Python).
  • Bukan untuk Big Data: Jangan gunakan code diatas untuk data yang besar. Untuk big data processing biasanya data dan proses di streaming (incremental) dari NoSQL dan tidak di-load semuanya ke memory seperti code diatas.
  • Tidak cocok untuk diparalelkan. Programmer HPC berpengalaman pasti ngeh bahwa coding untuk program serial dan parallel seringnya memiliki struktur/teknik yang berbeda. Namun hal tersebut diluar jangkauan artikel pendahuluan ini.

Penutup

Mudah sekali kan ya? … iya kan? .. ya? … #maksa … :) … Seperti biasa jika ada pertanyaan atau perintah yang tidak dimengerti? Lagi-lagi silahkan komentar dibawah. Semoga bermanfaat dan best of luck … ;)

< / TES >® ~ BNE 01/08/2016,22:35:06

43 thoughts on “Text PreProcessing & Terms Distribution

  1. Hi mas, terima kasih atas tulisanyya. Saya tertarik untuk mempelajadi text mining dan NLP tapi saya gak ada basic sama sekali di bidang ini. untuk hal paling dasar untuk masuk ke bidang ini apa ya mas? dengan senang hati kalo berkenang posting series belajar bidang ini. Salam kenal mas

    • Hhmmm… sebenarnya saya senang share pengetahuan, sayangnya saya “moody” banget orangnya. Saya biasanya nulis sesuatu kalau saya sedang mood nulis dan mood tentang topik yang ada di pikiran saat itu. Untuk Text Mining, coba pelajari dari list daftar bacaan berikut, sepertinya cukup bagus: http://www.text-analytics101.com/2014/10/text-mining-ir-and-nlp-references.html

      Saran saya kalau ndak punya waktu banyak, langsung saja belajar dengan masalah-masalah terapan yang sederhana di text mining. Kalau punya waktu lebih banyak list bacaan diatas bisa digunakan. Good luck ya ….

    • CSV tidak self contained (portable), maksudnya ia memiliki headers yg fixed.
      Sayangnya Gephi, Tableau, dan beberapa software lainnya hanya bisa import dari CSV ya?

      Untuk mengimport Json ke CSV, terlebih dahulu tentukan headernya : dengan bahasa yang sederhana, kita tentukan dulu kolom satu mau simpan atribute apa, kolom dua apa, dst … setelah itu ditetapkan … jSon ==> CSV bisa dilakukan dengan mudah.

      Lain kali saya akan buatkan scriptnya & publish di web ini … kalau dalam sebulan belum ada juga post tsb… tolong ingatkan saya … akhir-akhir ini super sibuk sering lupa mengerjakan segala sesuatu …

      • Aahh.. menemukan case yg saya jumpai sekarang. Sudah download Python versi 3.5 Anaconda dan sedang mencoba script yg sdh diberikan tp masih bingung utk merubah header2 apa saja yg ingin saya buat. Kira2 ada suggest scriptnya seperti apa kak taufik? masi mentok.

      • #Pak sy coba code dibawah untk import json tweet ke CSV dengan mem filter objek yg sy butuhkan tpi error.. ! ada saran ga pak?? terimakasih…

        import json
        import csv
        import sys
        from csv import writer

        with open(sys.argv[1]) as in_file, \
        open(sys.argv[2], ‘w’) as out_file:
        print >> out_file, ‘tweet_id, tweet_time, tweet_author, tweet_author_id,tweet_language, tweet_text’
        csv = writer(out_file)
        tweet_count = 0

        for line in in_file:
        tweet_count += 1
        tweet = json.loads(line)

        row = (
        tweet[‘id’],
        tweet[‘created_at’],
        tweet[‘user’][‘screen_name’],
        tweet[‘user’][‘id_str’],
        tweet[‘lang’],
        tweet[‘text’]
        )
        values = [(value.encode(‘utf8’) if hasattr(value, ‘encode’) else value) for value in row]
        csv.writerow(values)

        print (“File Imported:”), str(sys.argv[1])
        print (“# Tweets Imported:”), tweet_count
        print (“File Exported:”), str(sys.argv[2])

    • Kalau brute force pairwise comparisons, sampai puluhan ribu sepertinya masih ok (gunakan parallel processing). Tapi ndak efisien untuk jumlah tweet jutaan. Saya belum pernah melakukan duplicate tweet filtering utk data besar, tapi saya pernah baca bisa menggunakan hashing (minHash) supaya komputasinya lebih cepat: https://en.wikipedia.org/wiki/MinHash

  2. pak mau tanya. Ada yang eror nii. Kenapa yaa? TT
    mohon solusinya pak. Terima kasih

    >>> runfile(‘C:/Users/user/.spyder2/test.py’, wdir=’C:/Users/user/.spyder2′)
    Traceback (most recent call last):
    File “”, line 1, in
    File “C:\Users\user\Anaconda2\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py”, line 699, in runfile
    execfile(filename, namespace)
    File “C:\Users\user\Anaconda2\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py”, line 74, in execfile
    exec(compile(scripttext, filename, ‘exec’), glob, loc)
    File “C:/Users/user/.spyder2/test.py”, line 27, in
    sw=open(StopWords,encoding=’utf-8′, mode=’r’);stop=sw.readlines();sw.close()
    TypeError: ‘encoding’ is an invalid keyword argument for this function

  3. pak mau nanya ne, ada yang error

    w=dSorted[0];D=dSorted[1];f=dSorted[2]
    IndexError: list index out of range

    apa solusinya pak?

      • klo saya kasih data hasil crawl dari script bapak bisa, tp saat saya kasih data dari crawl script saya errornya msh ada pk, “list index out of range”. utk tipe datanya sama yaitu json. jumlah data jg sdh sy samakan 300.. kira2 apa yang salah ya pak?

  4. Terimakasih banyak atas tulisannya, saya terbantu sekali dalam penyusunan TA yagn sedang dijalani kebetulan saja mengambil topik Sentiment Analysis, ohiya kalo untuk crawling nya itu sendiri bagai mana ya pak? terimakasih..

  5. Dear Kang Taufik,

    Kang, kalo di phyton bisa crawling berdasar waktu tweet nggk ya? misal saya mau ngambil data dengan hastag/keyword tanggal 1 Januari 2016 s/d 11 November 2016?

    Hatur nuhun.

    Wass,
    Rian

  6. Dear kang Taufik.

    kalo mau tentuin atau dapetin lokasi (longitude-latitude) dari tweet gimana ya? ada masukan ga kang? soalnya nanti representasi datanya pakai peta.
    ini contoh tweetnya:

    “@pln_123 jl flamboyan kec medan selayang mati lampu gelap bgt smua,lampu lalulintas mati macet.Tolong hidupin segera ,trimakasih”
    “@TMCPoldaMetro 17:19 Terjadi kecelakaan di KM 47, Tol Merak (arah Jakarta) & Masih petugas #Polri. (Foto:@nugrahareza46)”

    Terima kasih sebelumnya kang

  7. Terimakasih sharing ilmunya, saya sangat terbantu ketika melakukan crawling berkat post sebelumnya. Saat ini saya sedang belajar mengenai preprocessing, dan mau bertanya, kenapa waktu running di python 3 ada problem ImportError: No module named ‘_sqlite3’ ya? padahal saya sudah menginstall dan import sqlite..
    Kalau saya run di python 2 problemnya ImportError: No module named nltk padahal sudah install nltk –> pip3 install nltk
    Requirement already satisfied: nltk in /usr/local/lib/python3.5/site-packages

    Saya sudah mencoba berbagai solusi dr askubuntu, stackoverflow dkk tetapi belum mendapat solusi yang tepat, siapa tahu bapak berkenan membantu saya, jadi mohon pencerahannya hehe, terimakasih :)

    • Saya sudah berhasil mengatasi problem yang saya tanyakan kemarin Pak, bisa dihapus saja ini hehe trims..

  8. Assalamualaikum bapak
    Semoga bapak sehat selalu yaa pak :)
    Pak saya Mohamad Irvan. Alumni Matematika FST UIN Jakarta.
    Saya ingin bertanya pak

    stream.filter(locations = [106.20,-6.41,107.19,-6.01]) —>> bagian ini untuk memfilter lokasi jabodetabek

    bisakah jika saya ingin menambah filter tweet yang diambil dari twitter ketika proses crawling dilokasi tersebut yang hanya berbahasa indonesia pada hari tertentu tanpa harus ada target topik pencarian? Maksud saya disini, saya ingin mengambil semua tweet dilokasi tersebut yang hanya berbahasa indonesia selama satu hari ditanggal tertentu

    • Setau saya hal ini tidak bisa dilakukan.
      Kalau mau dipaksakan, pakai beberapa machine [komputer], lalu masing-masing melakukan streaming/crawling suatu blok [himpunan kata] dalam kosa kata bahasa indonesia [non-stopwords].
      Tapi kendalanya nanti banyak duplikasi. Infrastruktur systemnya juga jadi riweuh ….

Leave a Reply