Membuat Mood Tracking dengan Python

DW ADS

Halo sobat Exsight, salam kenal semua! Pada artikel kali ini, aku diberikan kesempatan oleh tim Exsight untuk menjadi penulis tamu nih. Di kesempatan kali ini, aku akan membahas salah satu episode “Data Slices” yang terakhir kubuat tentang Mood Tracking menggunakan Python. 

Jadi “Data Slices” adalah sebuah series data visualisasi yang aku buat, dimana aku membuat data visualisasi yang menarik dari data-data random yang aku temukan menggunakan beberapa libraries yang ada di Python (seperti Matplotlib atau Seaborn) dan Jupyter notebook. Buat kalian yang penasaran dengan series “Data Slices” yang aku buat, kalian bisa langsung mengunjungi GitHub repo nya di sini.

Nah, di episode terakhir “Data Slices”, aku membuat dua buah visualisasi, dimana aku menampilkan emosi (mood) yang aku rasakan sepanjang harinya selama tahun 2023 dan report (rangkuman) dari mood yang aku catat sepanjang tahun tersebut. Di artikel ini, aku akan membahas background story project, teknik pengumpulan data, code overview dari data visualisasi yang aku buat, hingga hal-hal yang aku pelajari dari project ini. Aku pun juga sudah mencantumkan gambar data visualisasi yang aku sebutkan di bawah paragraf ini yah. Tanpa berlama-lama lagi, yuk simak artikel ini dengan seksama!

Figur “Mood Report”

Background Story

Pastinya sobat Exsight familiar dong dengan yang namanya resolusi tahun baru? Nah, buat sebagian orang, resolusi tahun baru sangatlah penting buat mereka yang ingin mencapai sesuatu yang diinginkan ataupun yang ingin berubah menjadi lebih baik di tahun yang akan datang. Dan, waktu yang tepat untuk memikirkan hal-hal tersebut adalah di akhir tahun, dimana akhir tahun memperbolehkan kita untuk merefleksikan apa yang sudah berlalu di tahun itu dan juga menetapkan tujuan-tujuan baru yang ingin dicapai dalam jangka waktu setahun yang akan datang. Salah satu orang yang selalu membuat resolusi di tahun baru tersebut adalah aku hehehe. 

Jadi, pada akhir tahun 2022 kemarin, dan sebagai persiapan dalam menyambut tahun 2023, aku pun juga ikut mulai memikirkan hal-hal dan kebiasaan baru apa saja yang ingin kucoba dan tekuni, sekaligus kebiasaan buruk yang ingin ditinggalkan di tahun tersebut.

 

Habit plan ku di tahun 2023

Ketika aku menentukan habit baru apa saja yang ingin kucoba, ada satu habit yang cukup menarik perhatianku untuk dicoba, yaitu journaling. Kenapa journaling? Karena ketika aku melakukan research terkait itu, aku menemukan beberapa hal bermanfaat yang bisa aku dapatkan, baik secara emosional maupun personal, contohnya lebih memahami emosi yang dirasakan di hari itu, latihan bersyukur, refleksi diri (apa yang baik terjadi di hari itu, apa yang dapat diperbaiki/ditingkatkan, apa yang tidak berjalan sesuai harapan), peningkatan produktivitas, dan sebagainya.

Nah, karena salah satu manfaat dari journaling ini adalah mengenali emosi yang dirasakan, aku pun akhirnya juga berencana untuk membuat suatu mood tracker, dimana aku mencatat emosi yang aku rasakan setiap harinya sembari melakukan journaling secara manual di buku tulis pribadi. Rencananya juga, mood tracker yang bakalan aku buat ini nantinya akan ditampilkan sebagai salah satu episode dari series “Data Slices”, dimana visualisasi yang bakalan dibuat akan berupa kalender yang memperlihatkan naik turunnya emosi yang aku rasakan setiap harinya sepanjang tahun 2023.

Pengumpulan Data

Karena project kali ini tidak hanya mencatat mood harian tetapi juga mencatat habit yang akan dibentuk selama tahun 2023, maka aku memutuskan untuk mencatatnya di sebuah spreadsheet menggunakan Google sheet. Tampilan dari spreadsheet-nya bisa kalian lihat pada gambar di bawah ini yah. Jadi, untuk mempermudah proses pencatatan data setiap harinya dan untuk memastikan tidak ada data kotor/anomali, aku memutuskan untuk membuat semacam dropdown button di setiap kolom habit dan mood, agar value yang terekam di spreadsheet akan terus konsisten setiap saat. 

Spreadsheet yang aku buat juga mencatat nama hari, tanggal, dan juga bulan untuk mempermudah filtering data ketika melakukan proses pencatatan mood dan habit pada hari dan bulan tertentu. Nah, buat kalian yang ingin melihat spreadsheet lengkapnya, kalian bisa melihatnya disini.

 

Spreadsheet untuk mencatat mood setiap harinya

Kemudian, untuk pengumpulan data mood ini mau tidak mau harus aku lakukan secara manual setiap harinya, yang dimana terkadang proses pengumpulan data ini cukup membuat aku tersiksa hahaha. Tetapi, untuk menjadikan proses pengumpulan data ini menjadi lebih mudah dan bisa konsisten setiap harinya, maka aku pun mendapatkan ide untuk mengubah settingan di browser, dimana setiap kali aku membuka browser maka browser akan otomatis membuka tab baru ke spreadsheet yang telah aku buat. Settingan ini memperbolehkan aku untuk terus ingat dalam mencatat mood dan habit setiap harinya, sehingga tidak ada data yang missing ketika akan dibuat visualisasi nantinya.

 

Browser settings untuk mencatat mood setiap harinya

Code Overview

Pada bagian code overview ini, aku akan menjelaskan secara singkat flow code dari kedua visualisasi yang telah disebutkan sebelumnya. Karena ada dua tipe visualisasi yang aku buat, maka bagian ini aku akan pecah menjadi dua sub-bagian, yang pertama adalah “Emotional Journey” (visualisasi kalender) dan yang kedua adalah “Summary Report” (visualisasi rangkuman). Secara umum, library yang aku gunakan untuk membuat kedua visualisasi tersebut adalah sebagai berikut

# Importing Libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import emoji
import math

Nah setelah mengimport library yang akan digunakan, tahapan selanjutnya adalah mengimport dataset nya. Dataset dapat di download dari spreadsheet yang sudah aku lampirkan sebelumnya sebagai file CSV dan di import menggunakan Pandas di Python atau Jupyter notebook. Aku pun juga melakukan sedikit processing menggunakan Pandas, sehingga value yang akan ditampilkan di gambar nanti akan lebih mudah dipahami oleh audiens yang melihatnya.

# Importing Dataset
df = pd.read_csv("mood_tracker_2023.csv")

 

# Change Categorical to Numerical (Score based)
mood_dict = {
    "EMPTY": 0
    , "Awful": 1
    , "Bad": 2
    , "Below Average": 3
    , "Average": 4
    , "Above Average": 5
    , "Good": 6
    , "Great": 7
}
df["Mood"]=df["Mood"].replace(mood_dict)

Emotional Journey

Secara garis besar, langkah pertama untuk membuat figure yang menyerupai kalender tahunan adalah membuat dua array matriks kosong. Array matriks pertama adalah array yang akan berisikan tanggal, dan array kedua yang berisikan value 0 untuk diisi nantinya. Kedua array ini akan dibentuk berdasarkan tahun yang diinput dan disesuaikan bentuknya berdasarkan timestamp pada Pandas. Berikut adalah code untuk membuat kedua array tersebut.

def split_months(df, year):
    # Empty Matrices
    a = np.empty((6, 7))
    a[:] = np.nan
    day_nums = {m:np.copy(a) for m in range(1,13)}
    day_vals = {m:np.copy(a) for m in range(1,13)}
    # Shape Datatimes to Matrices in Calendar Layout
    date = pd.Timestamp(year=year, month=1, day=1) # Create timestamp based on year
    oneday = pd.Timedelta(1, unit='D') # Day +1
    while date.year == year:
        # If Value not Exist, Assign 0
        try:
            value=df[date]
        except KeyError:
            value=0
        # Get day and month number
        day, month = date.day, date.month
        # Sunday: +1; Saturday: no need
        col = (date.dayofweek+1) % 7
        if date.is_month_start:
            row = 0
        # Assign Day Number and Day Value to Empty Matrices
        day_nums[month][row, col] = day  # Day number (0-30/31)
        day_vals[month][row, col] = value # Value 
        if col == 6:
            row += 1
        date = date + oneday
    return day_nums, day_vals

Setelah membuat dua matriks tersebut, langkah selanjutnya adalah membuat figure-nya menggunakan Matplotlib. Disini, aku akan membuat terlebih dahulu variabel-variabel yang berisi value minimum dan maximum yang akan ditampilkan di Matplotlib. Selanjutnya, menggunakan Matplotlib, aku akan membuat kalender setiap bulannya dengan susunan kalender 3 kolom dengan 4 rows. Matriks yang berisi tanggal tadi akan di for loop dan ditampilkan menggunakan Matplotlib.

# --- Variables ---
vmin = df.min()
vmin = vmin if vmin < 0 else 0
vmax = df.max() 
day_nums, day_vals = split_months(df, year)
# --- Calendar Figure ---
fig, ax = plt.subplots(4, 3, figsize=(8.5, 11))
for i, axes in enumerate(ax.flat):
    # Creating Heatmap Figure
    axes.imshow(day_vals[i+1], cmap=color_map, vmin=vmin, vmax=vmax)

Agar bentuk kalender lebih terlihat proporsional, selanjutnya aku akan menambahkan nama bulan, nama hari, dan menghapus elemen-elemen yang tidak akan ditampilkan pada figure.

# --- Date Variables ---
WEEKS_IN_MONTH = 6
DAYS_IN_WEEK = 7
DAY_LABELS = ['S', 'M', 'T', 'W', 'T', 'F', 'S']
MONTH_LABELS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
# Month Title
axes.set_title(MONTH_LABELS[i], fontsize=9, fontweight=600)
# Labels
axes.set_xticks(np.arange(DAYS_IN_WEEK))
axes.set_xticklabels(DAY_LABELS, font=font_alt, fontsize=7)
axes.set_yticklabels([])
# Tick Marks
axes.tick_params(axis="both", which="both", length=0) 
axes.xaxis.tick_top()
# Modify Tick Locations
axes.set_xticks(np.arange(-0.5, 6, 1), minor=True)
axes.set_yticks(np.arange(-0.5, 5, 1), minor=True)
axes.grid(False)
# Despine
for spine in axes.spines.values(): spine.set_color("None")

Nah, sekarang figure yang ditampilkan formatnya sudah hampir menyerupai kalender nih. Agar lebih terlihat mirip kalender, disini aku akan menambahkan tanggal harian di pojok kanan atas setiap kotak hari nya dengan for loop.

# Annotate
for w in range(WEEKS_IN_MONTH):
    for d in range(DAYS_IN_WEEK):
        day_num = day_nums[i+1][w, d]
        # Add Annotation if Day Number is Valid Calendar Day
        if not np.isnan(day_num):
           day_num_text = axes.text(d+0.45, w-0.31, f"{int(day_num)}", ha="right", va="center", fontsize=5, alpha=0.8, color=color_line)

Kalian juga bisa menambahkan opsi-opsi lain yang tersedia di Matplotlib seperti Polygon, path effects, legend, atau judul, sehingga tampilan kalender nya akan lebih menarik lagi.

Summary Report

Sebelum masuk ke code flow untuk membuat gambar kedua, aku akan menjelaskan alasan pemilihan chart yang digunakan. Jadi, figure kedua ini adalah gabungan dari beberapa subplot yang kemudian digabung menjadi satu figure besar. Pada figure kedua ini, terdapat empat tipe subplot, yaitu:

    1. Gauge chart
      Gauge chart dipilih karena menurut aku tipe chart ini terbaik dalam menunjukkan progress dan metriks mood yang aku alami selama setahun penuh dibandingkan hanya menunjukkan nilai rata-rata.
    2. Stacked bar chart
      Sebenarnya, ada banyak pilihan dalam menampilkan persentase dari setiap kategori mood, contohnya histogram atau pie chart. Namun, menurut aku stacked bar chart akan lebih sesuai dalam menunjukan persentase setiap mood-nya, dikarenakan value dari chart ini dapat digolongkan ke satu kategori saja.
    3. Bar chart
      Bar chart dipilih karena chart ini cocok untuk menunjukkan progress mood dari awal hingga akhir tahun setiap bulannya. Selain itu, karena kategori yang ada di chart ini cukup sedikit, bar chart akan lebih cocok dibandingkan dengan line chart dikarenakan akan lebih gampang untuk melakukan komparasi nilai dari bulan yang satu ke yang lainnya.
    4. Line chart
      Untuk tipe ini, sama dengan poin sebelumnya, yaitu ingin menunjukkan progress dari awal hingga akhir tahun. Tetapi, karena kategori di chart ini lebih banyak dibandingkan chart sebelumnya, menurutku line chart akan lebih cocok digunakan dikarenakan chart ini cocok dalam menampilkan data point yang selalu berubah-ubah setiap saat.

Setelah memahami tipe-tipe chart dan alasan pemilihan visualisasi yang digunakan, selanjutnya aku akan membahas sedikit code yang akan digunakan untuk membuat masing-masing chart yang telah disebutkan.

Gauge Chart

Cara membuat gauge chart sebenarnya sama dengan cara membuat bar chart pada umumnya di Matplotlib. Namun, ketika akan menampilkan bar chart ini dalam subplot, perlu ditambahkan parameter “projection” agar bar chart yang ditampilkan nanti melengkung sehingga menyerupai gauge chart. Setelah bar dari gauge chart terbentuk, kalian bisa menambahkan arrow untuk menjelaskan rating atau value-nya. Berikut adalah code untuk membuat bar chart dan cara menampilkannya di dalam subplot:

# --- Figure Props ---
arrowkw = dict(arrowstyle="wedge, tail_width=0.4", facecolor=emoji_color, linewidth=1.5, edgecolor="white")
# --- Create Bar Chart ---
ax_meter.bar(x=x_axis_vals, width=0.5, height=0.5, bottom=2, linewidth=3.5, color=list_mood_color[::-1], edgecolor=face_color, align="edge")
ax_meter.annotate(" ", xytext=(0, 0), xy=(int(avg_mood)*0.22, 2.2), fontsize=60, arrowprops=arrowkw)
ax_text(x=0, y=0, s=f"{emojis}n<{avg_mood}/7>", ax=ax_meter, size=44, ha="center", va="center", font=font_emoji, color=emoji_color, highlight_textprops=highlight_prop)
# --- Showing Bar Chart in Semi-Circle Format (Gauge) ---
ax_meter = fig.add_subplot(gs[0, :1], projection="polar")

Stacked Bar Chart

Cara pembuatan stacked bar chart cukup sederhana, yaitu dengan cara membuat bar chart pada umumnya di Matplotlib. Agar tampilan dari bar chart tergabung menjadi satu kategori/menumpuk, kalian dapat menambahkan parameter “stacked” dengan value “True”. Kalian dapat menggunakan “barh” agar tampilan bar chart terlihat horizontal. Berikut adalah code untuk membuat stacked bar chart menggunakan Matplotlib:

# --- Creating Stacked Bar Chart ---
df_dist.plot.barh(stacked=True, ax=ax, legend=False, edgecolor=face_color, linewidth=2, color=dist_colors[1::])sd

Bar Chart

Untuk pembuatan bar chart, cara pembuatannya hampir mirip dengan code stacked bar seperti yang ditampilkan sebelumnya. Kalian hanya perlu mengurangi parameter “stacked” agar bar chart terlihat tidak menumpuk dan menggunakan “bar” agar tampilan bar chart terlihat vertikal.

# --- Plot ---
ax.bar(df_monthly["Month"], df_monthly["Avg Mood"], color=monthly_clr_list, **bar_prop)

Line Chart

Untuk line chart yang aku buat ini, terdiri dari 2 gabungan chart, yaitu scatter plot chart dan line chart itu sendiri. Scatter plot berfungsi sebagai markers dari line chart yang dibuat, agar lebih mudah dibaca. Jadi, langkah pertama untuk membuat gabungan chart ini adalah membuat line chart terlebih dahulu. Setelah line chart terbentuk, scatter plot akan diposisikan berada “diatas” line chart sehingga membentuk markers dari line chart. Berikut adalah code untuk membuat scatter dan line plot seperti di gambar:

# --- Line Plot ---
l0 = LineCollection(segment
                    , colors=df_weekly["Color"].str.lower()
                    , array=df_weekly["Color"].cat.codes
                    , linewidth=1)
ax.add_collection(l0)
ax.autoscale_view()
# --- Scatter Plot ---
l1 = ax.scatter(df_weekly["Week Number"], df_weekly["Mood"]
                      , color="white"
                      , marker="o"
                      , s=25
                      , edgecolor=df_weekly["Color"]
                      , zorder=3)

Oh ya, untuk kalian yang penasaran dengan code lengkapnya, kalian bisa mengunjungi Jupyter notebook yang ada di GitHub dengan mengklik link ini. Akupun juga sudah pernah menjelaskan project ini secara lebih detail lagi di video livestream yang ada di channel YouTube HaloTech Academy, replay video-nya bisa kalian lihat disini yah. Kalau kalian masih kebingungan, kalian bisa langsung menanyakan pertanyaan kalian di kolom komentar di bawah juga.

Insights

Figur “Mood Calendar”
Figur “Mood Report”

Dari visualisasi yang kubuat ini, aku bisa menyimpulkan bahwa dilihat dari rata-rata skor mood nya, tahun lalu (2023) adalah tahun yang cukup baik buat diriku. Jika dilihat dari distribution setiap kategori moodnya, ternyata di satu tahun terakhir itu mood yang aku alami tidak hanya “Above average” atau “Good” saja, tetapi ada juga “Great”, “Below Average”, ataupun “Bad”, walaupun persentase kategori mood ini tidak sebesar “Above Average” ataupun “Good”. 

Selain itu, perbedaan nilai mood antara hari satu dengan hari lainnya ternyata cukup signifikan walaupun perbedaannya hanya angka desimal. Contohnya, pada hari Senin dengan hari Sabtu atau Minggu. Walaupun sama-sama “Above Average”, tetapi ungkapan “I hate Monday” terbukti ada benarnya buat diriku di tahun lalu hahaha. Kesimpulan lainnya lagi adalah, bulan Desember adalah bulan paling menyenangkan buat diriku di tahun lalu. Hal ini karena nilai rata-rata mood di bulan Desember dan nilai rata-rata per minggunya lebih tinggi dibandingkan minggu-minggu dan bulan lainnya. Mungkin karena musim liburan kali yah, makanya skor mood nya bagus? Hehehe.

Hal-hal lain yang aku pelajari adalah, aku juga bisa lebih mengenali emosi yang kurasakan, karena dengan mencatat mood setiap hari ini, memperbolehkan aku untuk merefleksikan pola-pola mood tertentu sepanjang tahun serta lebih memahami kejadian apa yang paling mempengaruhi mood di hari itu. Contohnya, aku lebih memahami bulan-bulan di mana aku cenderung merasa lebih bahagia atau lebih stres. 

Selain itu, aku juga lebih memahami hari-hari dalam seminggu yang secara konsisten membuat mood aku lebih baik atau lebih buruk. Aku pun juga lebih memahami kejadian-kejadian, aktivitas, ataupun kebiasaan yang menyebabkan ups and downs nya emosi aku secara lebih detail lagi, serta mengetahui apa yang perlu diperbaiki atau ditingkatkan. Aku pun juga merasa lebih produktif dalam melakukan habit yang sudah kurencanakan di akhir tahun 2022.

Itu aja yang aku bisa sharing ke sobat Exsight terkait project yang aku buat. Jika kalian penasaran dengan visualisasi-visualisasi lain yang aku buat selain visualisasi diatas, kalian bisa langsung mengunjungi GitHub repository nya “Data Slices” disini

Kalau kalian tidak mau ketinggalan dengan visualisasi yang akan aku buat selanjutnya, kalian bisa langsung memfollow social media aku yang ada di https://linktr.ee/caesarmario_ atau men-star repository nya “Data Slices” disini. Stay tuned di website https://exsight.id/blog/ agar tidak ketinggalan artikel-artikel menarik lainnya. Bye bye!

Sstt...
Mau Kiriman Artikel Terbaru Exsight
Tanpa Biaya Langganan? ????

Nama Kamu

Email Kamu

Dapatkan Akses Informasi Terupdate Seputar Dunia Data dan Statistika 🙂

Exsight ADS

1 thought on “Membuat Mood Tracking dengan Python”

  1. Pingback: 10 Teknik Pada Pandas Yang Jarang Orang Ketahui - Exsight

Leave a Comment

Hubungi Admin
Halo, selamat datang di Exsight! 👋

Hari ini kita ada DISKON 20% untuk semua transaksi. Klaim sekarang!