0Pricing
R Academy · Pelajaran

Analisis Sentimen di R

Gabungkan token dengan leksikon sentimen untuk mengukur nuansa positif atau negatif.

Analisis Sentimen di R adalah pelajaran R Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar R Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus R Academy mencakup 4 pelajaran total.

Gambaran Umum Analisis Sentimen

Analisis sentimen menetapkan valensi emosional pada teks. Pendekatan tidytext mencocokkan kata satu per satu dengan leksikon sentimen, lalu menggabungkan skornya. Tersedia tiga leksikon bawaan: AFINN (skor numerik), Bing (positif/negatif), dan NRC (kategori emosi).

library(tidytext)

# Available sentiment lexicons
# AFINN: -5 to +5 numeric score
# Bing:  binary positive/negative
# NRC:   emotion categories (joy, fear, anger, ...)

# Preview AFINN
afinn_sample <- get_sentiments('afinn')
cat('AFINN rows:', nrow(afinn_sample), '\n')
cat('Score range:', range(afinn_sample$value), '\n')
print(head(afinn_sample, 5))

get_sentiments('afinn')

Leksikon AFINN memberikan skor bilangan bulat dari −5 (sangat negatif) hingga +5 (sangat positif) untuk 2.477 kata bahasa Inggris. Leksikon ini disusun oleh Finn Årup Nielsen dan bekerja dengan baik untuk media sosial serta teks ulasan.

library(tidytext)
library(dplyr)

afinn <- get_sentiments('afinn')

# Most positive and most negative words
cat('Most positive words:\n')
print(afinn |> slice_max(value, n = 5))

cat('\nMost negative words:\n')
print(afinn |> slice_min(value, n = 5))

# Score distribution
cat('\nScore distribution:\n')
print(table(afinn$value))

get_sentiments('bing')

Leksikon Bing (Bing Liu dan rekan-rekannya) mengklasifikasikan 6.786 kata sebagai positif atau negatif. Leksikon ini lebih besar daripada AFINN dan cocok untuk ulasan produk serta masukan pelanggan ketika polaritas sederhana sudah memadai.

library(tidytext)
library(dplyr)

bing <- get_sentiments('bing')

cat('Bing lexicon size:', nrow(bing), '\n')
cat('Positive words:', sum(bing$sentiment == 'positive'), '\n')
cat('Negative words:', sum(bing$sentiment == 'negative'), '\n')

# Sample positive and negative words
cat('\nSample positive:', head(bing$word[bing$sentiment == 'positive'], 8), '\n')
cat('Sample negative:', head(bing$word[bing$sentiment == 'negative'], 8), '\n')

inner_join: Menilai Kata

inner_join(tokens, afinn, by = 'word') hanya mempertahankan token yang muncul dalam leksikon AFINN, lalu menambahkan skornya. Kata yang tidak ada dalam leksikon akan dihapus secara diam-diam — ini merupakan kelebihan karena berfokus pada kata-kata sentimen yang dikenal, sekaligus keterbatasan.

library(tidytext)
library(dplyr)

reviews <- tibble::tibble(
  review_id = 1:3,
  text = c(
    'The product is excellent and outstanding quality',
    'Terrible experience, broken and disappointing',
    'Good value but slow delivery, acceptable overall'
  )
)

scored <- reviews |>
  unnest_tokens(word, text) |>
  inner_join(get_sentiments('afinn'), by = 'word')

cat('Scored words:\n')
print(scored[, c('review_id', 'word', 'value')])

Sentimen Bersih per Dokumen

Jumlahkan skor AFINN untuk setiap dokumen dengan group_by(document) |> summarise(sentiment = sum(value)) untuk memperoleh skor sentimen bersih. Jumlah positif menunjukkan sentimen keseluruhan yang positif; jumlah negatif menunjukkan sentimen yang negatif.

library(tidytext)
library(dplyr)

reviews <- tibble::tibble(
  review_id = 1:5,
  text = c(
    'excellent outstanding perfect love best amazing',
    'terrible broken horrible awful waste money',
    'good acceptable okay decent average',
    'brilliant fantastic outstanding love recommend',
    'poor bad disappointing slow useless'
  )
)

net_sentiment <- reviews |>
  unnest_tokens(word, text) |>
  inner_join(get_sentiments('afinn'), by = 'word') |>
  group_by(review_id) |>
  summarise(
    sentiment  = sum(value),
    word_count = n()
  ) |>
  mutate(polarity = ifelse(sentiment > 0, 'positive', 'negative'))

print(net_sentiment)

Sentimen Bing: Jumlah Positif vs Negatif

Dengan leksikon Bing, bandingkan jumlah kata positif dan negatif untuk setiap dokumen. Hitung sentiment = positive_n - negative_n untuk memperoleh skor polaritas bersih, atau gambarkan kedua jumlah tersebut sebagai batang berkelompok untuk melihat komposisinya.

library(tidytext)
library(dplyr)

corpus <- tibble::tibble(
  chapter = 1:4,
  text = c(
    'the hero was brave courageous strong and victorious in battle',
    'disaster struck terrible losses failure defeat mourning grief',
    'love joy happiness beautiful peaceful wonderful morning',
    'evil darkness corrupt wicked terrible pain suffering fear'
  )
)

bing_sentiment <- corpus |>
  unnest_tokens(word, text) |>
  inner_join(get_sentiments('bing'), by = 'word') |>
  count(chapter, sentiment) |>
  tidyr::pivot_wider(names_from = sentiment, values_from = n, values_fill = 0) |>
  mutate(net = positive - negative)

print(bing_sentiment)

Sentimen berdasarkan Bab atau Bagian

Untuk melacak sentimen sepanjang alur naratif, hitung sentimen bersih untuk setiap bab atau jendela bergulir. Hal ini mengungkapkan struktur emosional: peningkatan konflik, klimaks, dan penyelesaian. Gunakan ggplot2 dengan geom_line() atau geom_bar() untuk memvisualisasikan alur tersebut.

library(tidytext)
library(dplyr)
library(ggplot2)

# Simulate a 10-chapter story arc
set.seed(42)
chapters <- tibble::tibble(
  chapter = 1:10,
  text    = c(
    'peaceful beautiful joy love happy wonderful',
    'good friends happy carefree enjoyable fun',
    'worried anxious trouble fear uncertain dark',
    'danger terrible threat awful pain suffering',
    'fear horror disaster terrible devastation loss',
    'fight battle struggle hard difficult challenge',
    'hope courage determination brave strong resist',
    'triumph victory success celebrate joy love',
    'relief peace gratitude wonderful blessed happy',
    'love joy peace beautiful grateful wonderful'
  )
)

arc <- chapters |>
  unnest_tokens(word, text) |>
  inner_join(get_sentiments('afinn'), by = 'word') |>
  group_by(chapter) |>
  summarise(net_sentiment = sum(value))

ggplot(arc, aes(chapter, net_sentiment)) +
  geom_line(color = 'steelblue', linewidth = 1.2) +
  geom_hline(yintercept = 0, linetype = 'dashed') +
  labs(x = 'Chapter', y = 'Net Sentiment', title = 'Story Sentiment Arc') +
  theme_minimal()

Leksikon NRC: Kategori Emosi

Leksikon NRC (Saif Mohammad & Peter Turney) mengategorikan 13.901 kata ke dalam delapan emosi (kemarahan, antisipasi, jijik, ketakutan, kegembiraan, kesedihan, keterkejutan, kepercayaan) serta kategori positif/negatif. Saring berdasarkan emosi dengan filter(sentiment == 'joy').

library(tidytext)
library(dplyr)

nrc <- get_sentiments('nrc')
cat('NRC size:', nrow(nrc), '\n')
cat('Emotions:', paste(unique(nrc$sentiment), collapse = ', '), '\n')

# Words associated with 'joy'
joy_words <- nrc |> filter(sentiment == 'joy')
cat('\nJoy words:', nrow(joy_words), '\n')
cat('Sample:', head(joy_words$word, 10), '\n')

# Count words per emotion
nrc |>
  count(sentiment, sort = TRUE) |>
  print()

Menerapkan NRC pada Korpus

Gabungkan teks yang telah ditokenisasi dengan NRC untuk menilai setiap emosi secara terpisah. Agregasikan berdasarkan dokumen dan emosi menggunakan count(doc_id, sentiment) untuk melihat emosi mana yang paling dominan dalam setiap dokumen.

library(tidytext)
library(dplyr)

docs <- tibble::tibble(
  doc_id = c(1, 1, 2, 2, 3, 3),
  text   = c(
    'wonderful joyful happy love peace',
    'excited surprise anticipation trust',
    'fear anger terrible hate disgust',
    'dark horrible awful suffering pain',
    'curious wonder discovery learning',
    'hope trust anticipation future growth'
  )
)

nrc_scores <- docs |>
  unnest_tokens(word, text) |>
  inner_join(get_sentiments('nrc'), by = 'word') |>
  filter(!sentiment %in% c('positive', 'negative')) |>  # keep only emotions
  count(doc_id, sentiment, sort = TRUE)

cat('Emotion counts per document:\n')
print(nrc_scores)

Konsep Awan Kata

Awan kata memvisualisasikan frekuensi kata dengan ukuran teks yang sebanding dengan jumlah kemunculannya. Paket wordcloud atau wordcloud2 dapat membuatnya dari kerangka data kata/frekuensi. Warnai kata berdasarkan sentimen menggunakan leksikon Bing untuk menghasilkan awan yang warnanya menunjukkan sentimen.

library(tidytext)
library(dplyr)

# Prepare word frequencies coloured by Bing sentiment
corpus_text <- tibble::tibble(
  text = c(
    'excellent performance amazing results love beautiful',
    'terrible failure poor broken horrible waste',
    'brilliant outstanding success happy wonderful joy',
    'awful disappointing bad slow useless frustrating'
  )
)

word_freq <- corpus_text |>
  unnest_tokens(word, text) |>
  count(word, sort = TRUE) |>
  left_join(get_sentiments('bing'), by = 'word') |>
  mutate(
    sentiment = replace(sentiment, is.na(sentiment), 'neutral'),
    colour    = case_when(
      sentiment == 'positive' ~ '#2196F3',
      sentiment == 'negative' ~ '#F44336',
      TRUE                    ~ '#9E9E9E'
    )
  )

print(word_freq)
# In practice: wordcloud2(word_freq[, c('word','n')], color = word_freq$colour)

Keterbatasan Sentimen Berbasis Leksikon

Analisis sentimen berbasis leksikon memiliki beberapa kegagalan yang sudah diketahui: negasi ("tidak baik" dinilai positif), sarkasme ("wah bagus, ada bug lagi"), ketidakcocokan domain ("sick" bermakna positif dalam bahasa slang), dan kata-kata di luar kosakata. Pertimbangkan keterbatasan ini saat menafsirkan hasil.

library(tidytext)
library(dplyr)

# Negation problem
neg_examples <- tibble::tibble(
  text = c(
    'not good at all',   # negative, but 'good' scores +3
    'not bad',           # positive, but 'bad' scores -3
    'sick beats bro'     # slang positive, 'sick' is negative in AFINN
  )
)

scored <- neg_examples |>
  unnest_tokens(word, text) |>
  inner_join(get_sentiments('afinn'), by = 'word')

cat('Lexicon scores (naive - ignores negation):\n')
print(scored[, c('word', 'value')])
cat('\nNote: "not" is a stop word - the negation is lost!\n')

Pemeriksaan Singkat

Anda menggunakan inner_join(tokens, afinn, by = 'word') untuk menilai sentimen. Apa yang terjadi pada kata-kata dalam token Anda yang NOT ada dalam leksikon AFINN?

Ringkasan: Analisis Sentimen

Hal-hal penting:

  • Tiga leksikon utama: AFINN (skor −5 hingga +5), Bing (positif/negatif), NRC (8 emosi)
  • get_sentiments('afinn') / 'bing' / 'nrc' mengambil leksikon dalam bentuk tibble
  • inner_join(tokens, lexicon, by = 'word') hanya menilai kata yang cocok (kata yang tidak cocok dihapus)
  • Sentimen bersih = group_by(doc) |> summarise(sentiment = sum(value))
  • Bing: bandingkan jumlah kata positive - negative untuk setiap dokumen atau bagian
  • NRC: saring berdasarkan nama emosi untuk memisahkan ketakutan, kegembiraan, kemarahan, dan sebagainya
  • Keterbatasan utama: metode berbasis leksikon tidak menangani negasi, sarkasme, atau slang sesuai domain
library(tidytext)
library(dplyr)

tibble::tibble(text = 'excellent amazing love joy beautiful happy') |>
  unnest_tokens(word, text) |>
  inner_join(get_sentiments('afinn'), by = 'word') |>
  summarise(net_sentiment = sum(value)) |>
  print()

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Analisis Sentimen di R” gratis?

Ya — teks lengkap “Analisis Sentimen di R” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus R Academy, upgrade ke CoddyKit PRO. Kursus R Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Analisis Sentimen di R”?

Gabungkan token dengan leksikon sentimen untuk mengukur nuansa positif atau negatif. Kamu berlatih R Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai R Academy?

Tidak diperlukan pengalaman sebelumnya. R Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Analisis Sentimen di R” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran R Academy ini?

Ya. Setiap pelajaran R Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Tokenisasi dan Penghapusan Kata Henti
  2. TF-IDF dan Analisis Frekuensi Istilah
  3. Analisis Sentimen di R
  4. Pemodelan Topik dengan LDA
← Kembali ke R Academy