---
title: "Baza podataka katoličkog digitalnog medijskog prostora (2021-2025)"
date: last-modified
format:
html:
theme: cosmo
toc: true
smooth-scroll: true
---
```{r}
#| label: setup
#| include: false
knitr::opts_chunk$set(
echo = FALSE,
warning = FALSE,
message = FALSE,
fig.width = 4,
fig.height = 3,
dpi = 300
)
# Učitavanje potrebnih knjižnica
library(data.table)
library(dplyr)
library(ggplot2)
library(DT)
library(kableExtra)
library(plotly)
library(lubridate)
library(stringr)
library(corrplot)
library(skimr)
```
```{r}
#| label: load-data
#| echo: false
# Učitavanje podataka
dta <- readRDS("../data/merged_comprehensive.rds")
# Konverzija u data.table ako nije
if (!inherits(dta, "data.table")) {
dta <- as.data.table(dta)
}
# Izračun osnovnih statistika
n_records <- format(nrow(dta), big.mark = ",")
n_vars <- ncol(dta)
# Određivanje vremenskog raspona
if ("DATE" %in% names(dta)) {
date_col <- as.Date(dta$DATE)
min_year <- min(year(date_col), na.rm = TRUE)
max_year <- max(year(date_col), na.rm = TRUE)
time_period <- paste0(min_year, " - ", max_year, " godina")
} else {
time_period <- "2021.- 2025."
}
```
Baza podataka sadrži **`r n_records`** medijskih objava prikupljenih tijekom `r time_period`, fokusiranih na katoličke teme i sadržaje u hrvatskim medijima. Baza predstavlja sveobuhvatan korpus za analizu medijskog diskursa, sentimenta i angažmana publike u domeni katoličkih (religijskih) tema.
```{r}
#| label: basic-info-table
#| echo: false
# Dinamičko kreiranje osnovnih informacija
basic_info <- data.frame(
Karakteristika = c("Broj zapisa", "Broj varijabli", "Vremenski period", "Format", "Glavni jezik", "Geografski opseg"),
Vrijednost = c(
n_records,
as.character(n_vars),
time_period,
"R data.table",
"Hrvatski (hr)",
"Hrvatska (HR)"
)
)
kable(basic_info, caption = "Osnovne karakteristike dataseta") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))
```
## Struktura podataka
```{r}
#| label: data-structure
# Prikaz prvih nekoliko varijabli i njihovih tipova
var_types <- sapply(dta, class)
var_types_simple <- sapply(var_types, function(x) x[1])
# Prikaz strukture
cat(paste0("Classes 'data.table' and 'data.frame': ", nrow(dta), " obs. of ", ncol(dta), " variables:\n"))
# Prikaži prvih 10 varijabli
for (i in seq_len(min(10, ncol(dta)))) {
var_name <- names(dta)[i]
var_type <- var_types_simple[i]
sample_vals <- head(dta[[var_name]], 3)
sample_str <- paste0("'", substr(as.character(sample_vals), 1, 25), "'", collapse = " ")
cat(paste0("$ ", var_name, paste(rep(" ", max(1, 25 - nchar(var_name))), collapse = ""),
": ", var_type, " ", sample_str, " ...\n"))
}
if (ncol(dta) > 10) {
cat(paste0("... [dodatnih ", ncol(dta) - 10, " varijabli]\n"))
}
```
## Distribucija po godinama
```{r}
#| label: yearly-distribution
if ("DATE" %in% names(dta)) {
dta[, year := year(as.Date(DATE))]
yearly_counts <- dta[, .N, by = year][order(year)]
kable(yearly_counts,
caption = "Broj objava po godinama",
col.names = c("Godina", "Broj objava")) %>%
kable_styling(bootstrap_options = c("striped", "hover"))
}
```
# Opis varijabli
## Vremenske varijable
```{r}
#| label: temporal-vars
# Dinamička provjera postojanja varijabli
temporal_vars_list <- c("DATE", "TIME", "year")
temporal_vars_exist <- temporal_vars_list[temporal_vars_list %in% names(dta)]
temporal_vars <- data.frame(
Varijabla = c("DATE", "TIME", "year"),
Tip = c("character", "character", "numeric"),
Opis = c(
"Datum objave u formatu YYYY-MM-DD",
"Vrijeme objave u formatu HH:MM:SS",
"Godina izvlučena iz datuma"
),
Prisutno = c("DATE", "TIME", "year") %in% names(dta)
)
kable(temporal_vars[, 1:3], caption = "Vremenske varijable") %>%
kable_styling(bootstrap_options = c("striped", "hover"))
```
## Sadržaj i metapodaci
```{r}
#| label: content-vars
content_vars <- data.frame(
Varijabla = c("TITLE", "FULL_TEXT", "MENTION_SNIPPET", "AUTHOR", "FROM", "URL", "URL_PHOTO"),
Tip = c("character", "character", "character", "character", "character", "character", "character"),
Opis = c(
"Naslov članka/objave",
"Potpuni tekst objave (dostupan isključivo na zahtjev)",
"Isječak teksta koji sadrži ključne riječi",
"Autor objave (ako je dostupan)",
"Izvor/domena web stranice",
"Potpuna URL adresa objave",
"URL fotografije povezane s objavom"
)
)
kable(content_vars, caption = "Sadržaj i metapodaci") %>%
kable_styling(bootstrap_options = c("striped", "hover"))
```
## Kategorizacija i označavanje
```{r}
#| label: categorization-vars
cat_vars <- data.frame(
Varijabla = c("SOURCE_TYPE", "GROUP_NAME", "KEYWORD_NAME", "FOUND_KEYWORDS", "TAGS", "LANGUAGES", "LOCATIONS"),
Tip = c("factor", "character", "character", "character", "logical", "character", "character"),
Opis = c(
"Tip izvora (web, youtube, facebook, twitter itd.)",
"Naziv grupe za praćenje",
"Naziv ključne riječi",
"Pronađene ključne riječi u tekstu",
"Dodatne oznake (trenutno prazno)",
"Jezik objave (hr, bs)",
"Geografska lokacija (HR)"
)
)
kable(cat_vars, caption = "Kategorizacija i označavanje") %>%
kable_styling(bootstrap_options = c("striped", "hover"))
```
## Sentiment analiza
```{r}
#| label: sentiment-vars
sentiment_vars <- data.frame(
Varijabla = c("AUTO_SENTIMENT", "MANUAL_SENTIMENT"),
Tip = c("character", "logical"),
Opis = c(
"Automatski detektirani sentiment (positive/neutral/negative)",
"Ručno označen sentiment (trenutno prazno)"
)
)
kable(sentiment_vars, caption = "Sentiment analiza") %>%
kable_styling(bootstrap_options = c("striped", "hover"))
```
## Distribucija sentimenta
```{r}
#| label: sentiment-distribution
if ("AUTO_SENTIMENT" %in% names(dta)) {
sentiment_dist <- dta[!is.na(AUTO_SENTIMENT), .N, by = AUTO_SENTIMENT][order(-N)]
sentiment_dist[, Postotak := round(N / sum(N) * 100, 1)]
kable(sentiment_dist,
caption = "Distribucija automatskog sentimenta",
col.names = c("Sentiment", "Broj zapisa", "Postotak (%)")) %>%
kable_styling(bootstrap_options = c("striped", "hover"))
}
```
## Metrike angažmana
```{r}
#| label: engagement-vars
engagement_vars <- data.frame(
Varijabla = c("REACH", "VIRALITY", "ENGAGEMENT_RATE", "INTERACTIONS", "FOLLOWERS_COUNT"),
Tip = c("numeric", "numeric", "numeric", "numeric", "numeric"),
Opis = c(
"Doseg objave (broj ljudi koji je vidjelo)",
"Indeks viralnosti",
"Stopa angažmana (%)",
"Ukupan broj interakcija",
"Broj pratitelja autora"
)
)
kable(engagement_vars, caption = "Metrike angažmana") %>%
kable_styling(bootstrap_options = c("striped", "hover"))
```
## Specifične reakcije (Facebook)
```{r}
#| label: facebook-vars
fb_vars <- data.frame(
Varijabla = c("LIKE_COUNT", "LOVE_COUNT", "WOW_COUNT", "HAHA_COUNT", "SAD_COUNT", "ANGRY_COUNT", "COMMENT_COUNT", "SHARE_COUNT", "TOTAL_REACTIONS_COUNT"),
Tip = rep("numeric", 9),
Opis = c(
"Broj 'like' reakcija",
"Broj 'love' reakcija",
"Broj 'wow' reakcija",
"Broj 'haha' reakcija",
"Broj 'sad' reakcija",
"Broj 'angry' reakcija",
"Broj komentara",
"Broj dijeljenja",
"Ukupan broj svih reakcija"
)
)
kable(fb_vars, caption = "Specifične reakcije (Facebook)") %>%
kable_styling(bootstrap_options = c("striped", "hover"))
```
# Kvaliteta i kompletnost podataka
## Pregled nedostajućih vrijednosti
```{r}
#| label: missing-data
# Dinamički izračun nedostajućih vrijednosti
calc_missing <- function(x) {
round(sum(is.na(x) | x == "" | x == "NA") / length(x) * 100, 1)
}
# Odabir ključnih varijabli za provjeru
key_vars <- c("AUTHOR", "TAGS", "MANUAL_SENTIMENT", "FOLLOWERS_COUNT",
"REDDIT_SCORE", "VIEW_COUNT", "FULL_TEXT", "URL_PHOTO")
key_vars_exist <- intersect(key_vars, names(dta))
missing_reasons <- c(
AUTHOR = "Nije uvijek dostupno od izvora",
TAGS = "Funkcionalnost nije implementirana",
MANUAL_SENTIMENT = "Ručno označavanje nije provedeno",
FOLLOWERS_COUNT = "Ovisi o platformi i dostupnosti",
REDDIT_SCORE = "Specifično za Reddit objave",
VIEW_COUNT = "Specifično za video sadržaj",
FULL_TEXT = "Dostupno na zahtjev",
URL_PHOTO = "Nije dostupno za sve objave"
)
if (length(key_vars_exist) > 0) {
missing_pct <- sapply(key_vars_exist, function(var) calc_missing(dta[[var]]))
missing_data <- data.frame(
Varijabla = names(missing_pct),
Nedostaje = as.numeric(missing_pct),
Razlog = missing_reasons[names(missing_pct)],
stringsAsFactors = FALSE
)
missing_data <- missing_data[order(-missing_data$Nedostaje), ]
kable(missing_data,
caption = "Pregled nedostajućih vrijednosti u ključnim varijablama",
col.names = c("Varijabla", "Nedostaje (%)", "Razlog"),
row.names = FALSE) %>%
kable_styling(bootstrap_options = c("striped", "hover"))
} else {
# Prikaži nedostajuće vrijednosti za prvih 10 varijabli
first_vars <- head(names(dta), 10)
missing_pct <- sapply(first_vars, function(var) calc_missing(dta[[var]]))
missing_data <- data.frame(
Varijabla = names(missing_pct),
Nedostaje = as.numeric(missing_pct),
stringsAsFactors = FALSE
)
missing_data <- missing_data[order(-missing_data$Nedostaje), ]
kable(missing_data,
caption = "Pregled nedostajućih vrijednosti",
col.names = c("Varijabla", "Nedostaje (%)"),
row.names = FALSE) %>%
kable_styling(bootstrap_options = c("striped", "hover"))
}
```
## Statistički sažetak numeričkih varijabli
```{r}
#| label: numeric-summary
# Dinamički izračun statistika za numeričke varijable
target_vars <- c("REACH", "INTERACTIONS", "ENGAGEMENT_RATE", "LIKE_COUNT", "INFLUENCE_SCORE")
numeric_vars_exist <- intersect(target_vars, names(dta))
if (length(numeric_vars_exist) > 0) {
# Izračunaj statistike za svaku varijablu pojedinačno
stats_list <- lapply(numeric_vars_exist, function(var_name) {
x <- as.numeric(dta[[var_name]])
data.frame(
Varijabla = var_name,
Mean = mean(x, na.rm = TRUE),
Median = median(x, na.rm = TRUE),
SD = sd(x, na.rm = TRUE),
Min = min(x, na.rm = TRUE),
Max = max(x, na.rm = TRUE)
)
})
numeric_summary <- do.call(rbind, stats_list)
kable(numeric_summary,
caption = "Statistički sažetak ključnih numeričkih varijabli",
digits = 1,
row.names = FALSE) %>%
kable_styling(bootstrap_options = c("striped", "hover"))
} else {
# Pronađi bilo koje numeričke varijable u datasetu
all_numeric <- names(dta)[sapply(dta, is.numeric)]
if (length(all_numeric) > 0) {
vars_to_use <- head(all_numeric, 5)
stats_list <- lapply(vars_to_use, function(var_name) {
x <- as.numeric(dta[[var_name]])
data.frame(
Varijabla = var_name,
Mean = mean(x, na.rm = TRUE),
Median = median(x, na.rm = TRUE),
SD = sd(x, na.rm = TRUE),
Min = min(x, na.rm = TRUE),
Max = max(x, na.rm = TRUE)
)
})
numeric_summary <- do.call(rbind, stats_list)
kable(numeric_summary,
caption = "Statistički sažetak numeričkih varijabli",
digits = 1,
row.names = FALSE) %>%
kable_styling(bootstrap_options = c("striped", "hover"))
} else {
cat("Numeričke varijable nisu pronađene u datasetu.")
}
}
```
## Distribucija po izvorima
```{r}
#| label: source-distribution
if ("SOURCE_TYPE" %in% names(dta)) {
source_dist <- dta[!is.na(SOURCE_TYPE), .N, by = SOURCE_TYPE][order(-N)]
source_dist[, Postotak := round(N / sum(N) * 100, 1)]
kable(head(source_dist, 10),
caption = "Top 10 izvora po broju zapisa",
col.names = c("Tip izvora", "Broj zapisa", "Postotak (%)")) %>%
kable_styling(bootstrap_options = c("striped", "hover"))
}
```
# Primjeri korištenja
## Osnovne analize
```{r}
#| label: basic-analysis-table
# Kreiranje tablice osnovnih analiza
basic_analyses <- data.frame(
`Tip analize` = c(
"Analiza sentimenta po izvorima",
"Trendovi kroz vrijeme",
"Top izvori po angažmanu",
"Distribucija po godinama",
"Najčešće ključne riječi"
),
`R kod` = c(
"sentiment_by_source <- dta[, .N, by = .(FROM, AUTO_SENTIMENT)]",
"temporal_trends <- dta[, .N, by = .(year, month = substr(DATE, 6, 7))]",
"top_sources <- dta[, .(avg_engagement = mean(ENGAGEMENT_RATE, na.rm = TRUE)), by = FROM]",
"yearly_dist <- dta[, .N, by = year][order(year)]",
"keyword_freq <- dta[, .N, by = KEYWORD_NAME][order(-N)]"
),
`Rezultat` = c(
"Broj objava po izvoru i sentimentu",
"Broj objava po mjesecima",
"Prosječni angažman po izvoru",
"Broj objava po godinama",
"Frekvencija ključnih riječi"
),
`Sortiranje` = c(
"sentiment_by_source[order(-N)]",
"temporal_trends[order(year, month)]",
"top_sources[order(-avg_engagement)]",
"yearly_dist[order(year)]",
"keyword_freq[order(-N)]"
)
)
kable(basic_analyses,
caption = "Osnovne analize - pregled kodova i rezultata",
col.names = c("Tip analize", "R kod", "Rezultat", "Sortiranje")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
column_spec(2, width = "35%", extra_css = "font-family: monospace; font-size: 11px;") %>%
column_spec(4, width = "25%", extra_css = "font-family: monospace; font-size: 11px;")
```
## Napredne analize
```{r}
#| label: advanced-analysis-table
# Kreiranje tablice naprednih analiza
advanced_analyses <- data.frame(
`Analiza` = c(
"Tokenizacija teksta",
"Čišćenje stop riječi",
"Brojanje riječi po sentimentu",
"Sentiment scoring",
"Wordcloud generiranje",
"Vremenska serija angažmana",
"Korelacijska analiza"
),
`Potrebne biblioteke` = c(
"tidytext, dplyr",
"tidytext",
"dplyr, tidytext",
"dplyr, case_when",
"wordcloud, RColorBrewer",
"ggplot2, lubridate",
"corrplot"
),
`Ključni kod` = c(
"unnest_tokens(word, TITLE)",
"anti_join(stop_words)",
"count(word, AUTO_SENTIMENT, sort = TRUE)",
"summarise(sentiment_score = sum(n * case_when(...)))",
"wordcloud(words, freq, colors = brewer.pal(8, 'Dark2'))",
"ggplot(aes(x = DATE, y = ENGAGEMENT_RATE)) + geom_smooth()",
"corrplot(cor(numeric_vars, use = 'complete.obs'))"
),
`Očekivani output` = c(
"Pojedinačne riječi iz naslova",
"Filtrirane značajne riječi",
"Frekvencija riječi po sentimentu",
"Numerički sentiment score",
"Vizualna reprezentacija",
"Trend angažmana kroz vrijeme",
"Matrica korelacija"
)
)
kable(advanced_analyses,
caption = "Napredne analize - detaljni pregled metoda",
col.names = c("Analiza", "Potrebne biblioteke", "Ključni kod", "Očekivani output")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
column_spec(3, width = "30%", extra_css = "font-family: monospace; font-size: 10px;") %>%
scroll_box(width = "100%", height = "400px")
```
## Primjer koda za učitavanje i osnovnu obradu
```{r}
#| label: example-code
#| echo: true
#| eval: false
# Učitavanje podataka
dta <- readRDS("../../data/merged_comprehensive.rds")
# Konverzija datuma
dta[, DATE := as.Date(DATE)]
dta[, year := year(DATE)]
dta[, month := month(DATE)]
dta[, yearmonth := floor_date(DATE, "month")]
# Filtriranje po godinama
dta_2024_2025 <- dta[year %in% c(2024, 2025)]
# Agregacija po izvoru i sentimentu
summary_table <- dta[, .(
n_posts = .N,
avg_reach = mean(REACH, na.rm = TRUE),
avg_engagement = mean(ENGAGEMENT_RATE, na.rm = TRUE),
total_interactions = sum(INTERACTIONS, na.rm = TRUE)
), by = .(SOURCE_TYPE, AUTO_SENTIMENT)]
# Trend analiza
monthly_trend <- dta[, .(
n_posts = .N,
avg_sentiment_positive = mean(AUTO_SENTIMENT == "positive", na.rm = TRUE)
), by = yearmonth][order(yearmonth)]
```
# Tehnički detalji
## Izvorni format podataka
```{r}
#| label: technical-details-table
# Tehnički detalji u tabličnom formatu
technical_info <- data.frame(
`Kategorija` = c(
"Izvorne datoteke",
"Format obrade",
"Kodiranje",
"Separatori",
"Nedostajuće vrijednosti",
"Preporučena biblioteka Manipulacija",
"Preporučena biblioteka Sintaksa",
"Preporučena biblioteka Vizualizacija",
"Preporučena biblioteka Datumi",
"Preporučena biblioteka Tekst"
),
`Vrijednost/Opis` = c(
"merged_comprehensive.rds",
"R data.table",
"UTF-8",
"Automatski detektirani",
"NA",
"data.table za brzu manipulaciju velikih dataset-a",
"dplyr za čišću i čitljiviju sintaksu",
"ggplot2 za profesionalne vizualizacije",
"lubridate za rad s datumskim formatima",
"stringr za manipulaciju i analizu teksta"
),
`Napomene` = c(
"Svi podaci spojeni u jednu datoteku",
"Optimizirano za velike podatke",
"Podrška za hrvatske znakove",
"RDS format automatski parsiran",
"Standardno R označavanje",
"Brzina: 10-100x brža od base R",
"Kompatibilnost s tidyverse ekosystemom",
"Grammar of graphics pristup",
"Timezone aware operacije",
"Regex podrška za složene operacije"
)
)
kable(technical_info,
caption = "Tehnički detalji dataseta i preporučeni alati",
col.names = c("Kategorija", "Vrijednost/Opis", "Napomene")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
column_spec(2, width = "40%") %>%
column_spec(3, width = "35%") %>%
row_spec(1:5, background = "#f8f9fa") %>%
row_spec(6:10, background = "#e3f2fd")
```
## Napomene o performansama
```{r}
#| label: performance-notes
performance_tips <- data.frame(
Operacija = c(
"Čitanje podataka",
"Grupiranje i agregacija",
"Filtriranje velikih tekstova",
"Sortiranje po datumu",
"Analiza sentimenta",
"Eksport u CSV"
),
`Preporučeni pristup` = c(
"readRDS() za RDS format",
"data.table sintaksa [, .N, by=]",
"Koristiti grep() s fixed=TRUE",
"Konvertirati DATE u Date klasu",
"Koristiti existirajuće AUTO_SENTIMENT",
"fwrite() za brzi eksport"
),
`Očekivano vrijeme` = c(
"< 30 sekundi",
"< 5 sekundi",
"10-60 sekundi",
"< 10 sekundi",
"1-5 minuta",
"< 60 sekundi"
)
)
kable(performance_tips,
caption = "Preporuke za optimalne performanse",
col.names = c("Operacija", "Preporučeni pristup", "Očekivano vrijeme")) %>%
kable_styling(bootstrap_options = c("striped", "hover"))
```
# Potpuni popis varijabli
```{r}
#| label: full-variable-list
# Dinamički popis svih varijabli u datasetu
var_names <- names(dta)
all_vars <- data.frame(
Redni_broj = seq_along(var_names),
Varijabla = var_names,
Tip = sapply(var_names, function(v) class(dta[[v]])[1]),
N_jedinstvenih = sapply(var_names, function(v) length(unique(dta[[v]]))),
Nedostaje_pct = sapply(var_names, function(v) round(sum(is.na(dta[[v]])) / nrow(dta) * 100, 1)),
stringsAsFactors = FALSE
)
rownames(all_vars) <- NULL
kable(all_vars,
caption = "Potpuni popis varijabli u datasetu",
col.names = c("Br.", "Varijabla", "Tip", "N jedinstvenih", "Nedostaje (%)")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
scroll_box(width = "100%", height = "500px")
```
## Preuzmi bazu podataka
📊 **Kaggle Dataset** [Croatian Catholic Media Space 2021-2025](https://www.kaggle.com/datasets/lukasikic/croatian-catholic-digital-media-space/data)
```{r}
#| label: download-example
#| eval: false
# Direct download via Kaggle API
library(pins)
board <- board_kaggle()
dataset <- pin_read(board, "https://www.kaggle.com/datasets/lukasikic/croatian-catholic-digital-media-space/data")
# Alternativno, učitavanje lokalne verzije
dta <- readRDS("../../data/merged_comprehensive.rds")
```
# Licence i citiranje
Molimo citirajte ovu bazu u svojim radovima koristeći sljedeći format:
> **[Šikić, Luka/Hrvatsko katoličko sveučilište]**. (2025). *Katolički digitalni medijski prostor u Hrvatskoj 2021-2025*. Dataset sadrži `r n_records` medijskih objava iz hrvatskih medija. Pristupljeno `r Sys.Date()`.
## Dodatni resursi
- **GitHub repozitorij** [https://github.com/lusiki/DigiKat]
- **Dokumentacija** [https://lusiki.github.io/DigiKat/baza.html]
- **Kontakt** [luka.sikic@unicath.hr]
- **ORCID** [0009-0006-3519-0272]
---
**Zadnja ažurirana** `r Sys.Date()`
**Verzija** 2.0
**R verzija** `r R.version.string`