1
0
Files
Fundamenty-moralne/przygotuj_dane.R
T

358 lines
12 KiB
R
Raw Normal View History

2026-05-20 23:19:39 +02:00
# Przygotowanie danych do analiz projektu moralnosci
#
2026-05-23 00:20:59 +02:00
library(dplyr)
2026-05-20 23:19:39 +02:00
# Skrypt:
# 1. czyta surowe dane ankietowe,
# 2. czyta wyniki eksperymentu karcianego,
# 3. laczy zbiory po kodzie uczestnika,
# 4. przelicza zmienne skalowe opisane w pliku JSON,
# 5. zapisuje gotowe pliki CSV w katalogu outputs/.
#
# Uruchomienie z katalogu analiza-md:
# Rscript przygotuj_dane.R
args <- commandArgs(trailingOnly = FALSE)
file_arg <- grep("^--file=", args, value = TRUE)
base_dir <- if (length(file_arg) > 0) {
dirname(normalizePath(sub("^--file=", "", file_arg[1])))
} else {
getwd()
}
path <- function(...) file.path(base_dir, ...)
survey_file <- path("dane/badanie_18_wyniki_20260519_192209.csv")
experiment_file <- path("dane/Plan badania kartami(Wyniki gry).csv")
json_file <- path("dane/badanie_18_pytania_20260514_212146.json")
output_dir <- path("outputs")
dir.create(output_dir, showWarnings = FALSE)
clean_code <- function(x) {
x <- tolower(trimws(as.character(x)))
gsub("\\s+", "", x)
}
to_num <- function(x) {
x <- trimws(as.character(x))
x[x %in% c("", "NA", "NaN")] <- NA
x[x %in% c("Brak", "brak", "-", "brak danych")] <- NA
suppressWarnings(as.numeric(gsub(",", ".", x, fixed = TRUE)))
}
row_mean <- function(data, vars) {
out <- rowMeans(data[, vars, drop = FALSE], na.rm = TRUE)
out[is.nan(out)] <- NA_real_
out
}
row_sum <- function(data, vars) {
out <- rowSums(data[, vars, drop = FALSE], na.rm = TRUE)
all_missing <- rowSums(!is.na(data[, vars, drop = FALSE])) == 0
out[all_missing] <- NA_real_
out
}
rev_score <- function(x, max_value) {
ifelse(is.na(x), NA_real_, max_value + 1 - x)
}
survey <- read.csv2(
survey_file,
stringsAsFactors = FALSE,
check.names = FALSE,
fileEncoding = "UTF-8-BOM",
na.strings = c("", "NA")
)
head(survey)
colnames(survey)
# Nazwy ponizej odpowiadaja kolejnosci pytan opisanej w pliku JSON.
short_names <- c(
"kod_dostepu",
"data_zakonczenia",
"zgoda_stacjonarna",
"kod_uczestnika",
"plec",
"kierunek",
"wiek",
"rodzenstwo",
# numeracja z oryginalnych skal, niektóre skale zastosowano krótsze
paste0("mfq_zn_", c(1, 2, 3, 4, 6, 13, 12, 11, 10, 9, 8)),
paste0("mfq_oc_", c(16, 17, 18, 19, 21, 22, 23, 24, 26, 27, 28, 29)),
# klucz:
# Troska/krzywda 1,6,11,16,21,26
# Sprawiedliwość/oszustwo 2,7,12,17,22,27
# Lojalność/zdrada 3,8,13,18,23,28
# Autorytet/kwestionowanie władzy 4,9,14,19,24,29
paste0("aprobata_", c(1, 3, 8, 23, 11, 13, 14, 16, 20, 22)),
# klucz: 1P, 2F, 3F, 4P, 5F, 6P, 7F, 8P, 9F, 10P, 11P, 12F, 13F, 14P, 15P, 16P, 17P, 18F, 19P, 20P, 21P, 22F, 23F, 24P, 25F, 26P, 27F, 28F, 29P
paste0("neuro_", 1:12),
# odwrócone 1, 4, 7 ,10
paste0("prospol_", 1:8)
)
names(survey)[seq_along(short_names)] <- short_names
# usuwanie kolumn mierzących czas
time_cols <- grepl(" - Czas \\[s\\]$", names(survey))
survey <- survey[, !time_cols, drop = FALSE]
# poprawianie kodów
survey$kod_uczestnika_clean <- clean_code(survey$kod_uczestnika)
survey$kierunek_clean <- tolower(trimws(survey$kierunek))
survey$wiek <- to_num(survey$wiek)
# rodzenstwo na cyfry
rodzenstwo_txt <- trimws(as.character(survey$rodzenstwo))
rodzenstwo_txt[tolower(rodzenstwo_txt) == "brak"] <- "0"
survey$rodzenstwo <- to_num(rodzenstwo_txt)
# płeć na kategorie
survey$plec_etykieta <- ifelse(
survey$plec == 1, "kobieta",
ifelse(survey$plec == 2, "osoba niebinarna",
ifelse(survey$plec == 3, "mezczyzna",
ifelse(survey$plec == 4, "inna", NA)
)
)
)
# dodatkowo kierunek
survey$kierunek_grupa <- ifelse(
grepl("psycholog", survey$kierunek_clean), "psychologia",
ifelse(grepl("kognity", survey$kierunek_clean), "kognitywistyka",
ifelse(is.na(survey$kierunek_clean) | survey$kierunek_clean %in% c("", "-", "brak"), NA, "inny")
)
)
scale_vars <- c(
paste0("mfq_zn_", c(1, 2, 3, 4, 6, 13, 12, 11, 10, 9, 8)),
paste0("mfq_oc_", c(16, 17, 18, 19, 21, 22, 23, 24, 26, 27, 28, 29)),
paste0("aprobata_", c(1, 3, 8, 23, 11, 13, 14, 16, 20, 22)),
paste0("neuro_", 1:12),
paste0("prospol_", 1:8)
)
for (v in scale_vars) {
survey[[v]] <- to_num(survey[[v]])
}
# Moral Foundations Questionnaire: indeksy wedlug oryginalnej numeracji itemow.
survey$MFQ_TROSKA <- row_mean(survey, c("mfq_zn_1", "mfq_zn_6", "mfq_zn_11", "mfq_oc_16", "mfq_oc_21", "mfq_oc_26"))
survey$MFQ_SPRAWIEDLIWOSC <- row_mean(survey, c("mfq_zn_2", "mfq_zn_12", "mfq_oc_17", "mfq_oc_22", "mfq_oc_27"))
survey$MFQ_LOJALNOSC <- row_mean(survey, c("mfq_zn_3", "mfq_zn_8", "mfq_zn_13", "mfq_oc_18", "mfq_oc_23", "mfq_oc_28"))
survey$MFQ_AUTORYTET <- row_mean(survey, c("mfq_zn_4", "mfq_zn_9", "mfq_oc_19", "mfq_oc_24", "mfq_oc_29"))
# Aprobata spoleczna: wynik dla dostepnych itemow wedlug klucza P/F.
aprobata_items <- c(1, 3, 8, 23, 11, 13, 14, 16, 20, 22)
aprobata_scores <- data.frame(matrix(NA_real_, nrow = nrow(survey), ncol = length(aprobata_items)))
names(aprobata_scores) <- paste0("aprobata_score_", aprobata_items)
positive_true <- c(1, 8, 11, 14, 16, 20)
negative_false <- c(3, 13, 22, 23)
for (i in positive_true) {
aprobata_scores[[paste0("aprobata_score_", i)]] <- ifelse(is.na(survey[[paste0("aprobata_", i)]]), NA_real_,
ifelse(survey[[paste0("aprobata_", i)]] == 1, 1, 0)
)
}
for (i in negative_false) {
aprobata_scores[[paste0("aprobata_score_", i)]] <- ifelse(is.na(survey[[paste0("aprobata_", i)]]), NA_real_,
ifelse(survey[[paste0("aprobata_", i)]] == 2, 1, 0)
)
}
survey <- cbind(survey, aprobata_scores)
survey$APROBATA_SPOLECZNA <- row_sum(survey, names(aprobata_scores))
# Neurotycznosc: itemy spokojne/odwrotne to 1,4,7,10.
for (i in c(1, 4, 7, 10)) {
survey[[paste0("neuro_", i, "r")]] <- rev_score(survey[[paste0("neuro_", i)]], 5)
}
survey$NEUROTYCZNOSC <- row_mean(
survey,
c(
"neuro_1r", "neuro_2", "neuro_3", "neuro_4r", "neuro_5", "neuro_6",
"neuro_7r", "neuro_8", "neuro_9", "neuro_10r", "neuro_11", "neuro_12"
)
)
survey$PROSPOLECZNOSC <- row_mean(survey, paste0("prospol_", 1:8))
# Wyniki eksperymentu karcianego.
experiment_raw <- read.csv2(
experiment_file,
stringsAsFactors = FALSE,
check.names = FALSE,
fileEncoding = "UTF-8-BOM",
fill = TRUE
)
names(experiment_raw) <- trimws(names(experiment_raw))
names(experiment_raw)[1] <- "stacja"
experiment_raw <- experiment_raw[grepl("^stacaja_|^stacja_", experiment_raw$stacja), , drop = FALSE]
participant_cols <- setdiff(names(experiment_raw), "stacja")
participant_cols <- participant_cols[nzchar(trimws(participant_cols))]
clean_choice <- function(x) {
x <- tolower(trimws(as.character(x)))
x <- gsub("\\s+", "", x)
x[!(x %in% c("a", "b", "ab", "ba"))] <- NA
x
}
experiment_long <- do.call(rbind, lapply(participant_cols, function(code) {
choices <- clean_choice(experiment_raw[[code]])
data.frame(
kod_uczestnika_clean = clean_code(code),
stacja = seq_along(choices),
wybor_surowy = choices,
stringsAsFactors = FALSE
)
}))
experiment_long$stacja_id <- sprintf("stacja_%02d", experiment_long$stacja)
experiment_long$wybor_final <- ifelse(
experiment_long$wybor_surowy %in% c("a", "ba"), "a",
ifelse(experiment_long$wybor_surowy %in% c("b", "ab"), "b", NA)
)
experiment_long$zmiana_przekonania <- ifelse(
is.na(experiment_long$wybor_surowy), NA_real_,
ifelse(experiment_long$wybor_surowy %in% c("ab", "ba"), 1, 0)
)
experiment_long$silne_przekonanie <- ifelse(
is.na(experiment_long$wybor_surowy), NA_real_,
ifelse(experiment_long$wybor_surowy %in% c("a", "b"), 1, 0)
)
experiment_summary <- do.call(rbind, lapply(split(experiment_long, experiment_long$kod_uczestnika_clean), function(d) {
n_valid <- sum(!is.na(d$wybor_final))
data.frame(
kod_uczestnika_clean = d$kod_uczestnika_clean[1],
exp_n_stacji = n_valid,
zmiana_przekonania_n = sum(d$zmiana_przekonania == 1, na.rm = TRUE),
zmiana_przekonania_prop = ifelse(n_valid > 0, mean(d$zmiana_przekonania, na.rm = TRUE), NA_real_),
SILA_PRZEKONAN = ifelse(n_valid > 0, mean(d$silne_przekonanie, na.rm = TRUE), NA_real_),
stringsAsFactors = FALSE
)
}))
experiment_wide <- reshape(
experiment_long[, c("kod_uczestnika_clean", "stacja_id", "wybor_surowy", "wybor_final", "zmiana_przekonania")],
idvar = "kod_uczestnika_clean",
timevar = "stacja_id",
direction = "wide"
)
names(experiment_wide) <- gsub("\\.", "_", names(experiment_wide))
experiment_prepared <- merge(
experiment_summary,
experiment_wide,
by = "kod_uczestnika_clean",
all.x = TRUE,
sort = FALSE
)
merged <- merge(
survey,
experiment_prepared,
by = "kod_uczestnika_clean",
all.x = TRUE,
sort = FALSE
)
matched <- merged[!is.na(merged$exp_n_stacji), , drop = FALSE]
2026-05-23 00:20:59 +02:00
# liczenie fundamentów z gry
library(tidyverse)
# klucz stacji z pliku markdown
klucz_stacji <- readr::read_tsv("stacje.md", show_col_types = FALSE) |>
setNames(c("stacja", "fundament_a", "fundament_b")) |>
mutate(
negatywna = str_detect(stacja, "-"),
stacja = as.integer(str_remove(stacja, "-"))
)
score_ipsatywne_fundamenty <- function(dane,
klucz = klucz_stacji,
id_col = "kod_uczestnika_clean",
negative_weight = 1) {
fundamenty <- c("Troska", "Sprawiedliwość", "Lojalność", "Autorytet")
long <- dane |>
dplyr::select(dplyr::all_of(id_col), dplyr::matches("^wybor_final_stacja_\\d+$")) |>
tidyr::pivot_longer(
cols = dplyr::matches("^wybor_final_stacja_\\d+$"),
names_to = "stacja_col",
values_to = "wybor"
) |>
dplyr::mutate(
id = .data[[id_col]],
stacja = as.integer(stringr::str_extract(stacja_col, "\\d+")),
wybor = stringr::str_to_lower(as.character(wybor))
) |>
dplyr::left_join(klucz, by = "stacja") |>
dplyr::filter(wybor %in% c("a", "b")) |>
dplyr::mutate(
winner = dplyr::case_when(
wybor == "a" & !negatywna ~ fundament_a,
wybor == "b" & !negatywna ~ fundament_b,
wybor == "a" & negatywna ~ fundament_b,
wybor == "b" & negatywna ~ fundament_a
),
punkty = dplyr::if_else(negatywna, negative_weight, 1)
)
wyniki_raw <- long |>
dplyr::group_by(id, winner) |>
dplyr::summarise(punkty = sum(punkty), .groups = "drop") |>
tidyr::pivot_wider(
names_from = winner,
values_from = punkty,
values_fill = 0
) |> dplyr::arrange(id)
wyniki_raw
}
profil_fundamentow <- score_ipsatywne_fundamenty(matched, negative_weight = 0.5) |>
left_join(matched, by = c("id" = "kod_uczestnika_clean"))
# zapis
2026-05-20 23:19:39 +02:00
write.csv2(merged, path("outputs", "dane_polaczone_skale.csv"), row.names = FALSE, na = "")
2026-05-23 00:20:59 +02:00
write.csv2(profil_fundamentow, path("outputs", "dane_polaczone_skale_tylko_eksperyment.csv"), row.names = FALSE, na = "")
2026-05-20 23:19:39 +02:00
write.csv2(experiment_long, path("outputs", "wyniki_eksperymentu_long.csv"), row.names = FALSE, na = "")
write.csv2(experiment_prepared, path("outputs", "wyniki_eksperymentu_podsumowanie.csv"), row.names = FALSE, na = "")
duplicate_codes <- unique(survey$kod_uczestnika_clean[duplicated(survey$kod_uczestnika_clean)])
duplicate_codes <- duplicate_codes[!is.na(duplicate_codes) & nzchar(duplicate_codes)]
report <- c(
paste0("Plik ankietowy: ", basename(survey_file)),
paste0("Plik JSON: ", basename(json_file)),
paste0("Plik eksperymentu: ", basename(experiment_file)),
paste0("Liczba wierszy w ankiecie: ", nrow(survey)),
paste0("Liczba kodow w eksperymencie: ", length(unique(experiment_summary$kod_uczestnika_clean))),
paste0("Liczba wierszy po polaczeniu: ", nrow(merged)),
paste0("Liczba wierszy z wynikami eksperymentu: ", nrow(matched)),
paste0("Zdublowane kody w ankiecie: ", ifelse(length(duplicate_codes) == 0, "brak", paste(duplicate_codes, collapse = ", "))),
""
)
writeLines(report, path("outputs", "raport_przygotowania.txt"), useBytes = TRUE)
cat(paste(report, collapse = "\n"))
cat("\n")