ESCS 是單一的連續變項,題目要的是描述這批資料的集中和分散,不是比較組別,也不是做推論檢定。集中量數用平均數和中位數,變異性用標準差、全距和 IQR。平均數與標準差適合大致對稱的連續分布;中位數與 IQR 比較不受兩端極端值影響。兩組一起算,才能看出這份資料適不適合只看平均數。
ESCS(Index of economic, social and cultural status)是經濟、社會與文化地位的綜合指數。PISA 把它量成連續分數,OECD 平均大約是 0、標準差大約是 1,所以低於平均的人會是負數,負數不是錯誤代碼。
它不是類別,不能用次數分配當主要結果;它也不是只能取整數的次數,所以用平均數、標準差、分位數,而不是只數每一格有幾人。檔案標籤裡的 95、97、98、99 是跳答、不適用、無效、未答。這些代碼若留在資料裡,平均數和全距都會被拉得很誇張,所以分析前要先改成遺漏值。
haven 用來讀 SPSS 的
.sav。dplyr
用來挑欄位、改代碼、算摘要。ggplot2
畫分布圖,方便對照平均數和中位數;本題的圖表說明是略,圖只是用來核對形狀。knitr
的 kable() 把表排整齊。moments 算偏態。
Windows 的繪圖裝置不認得「微軟正黑體」這個名字,所以先用
windowsFonts() 登記成
JhengHei,圖上的中文才不會變方框。theme_set()
是把後面所有圖的底色、字級一次設好。
library(haven)
library(dplyr)
library(ggplot2)
library(knitr)
library(moments)
if (.Platform$OS.type == "windows") {
windowsFonts(JhengHei = windowsFont("Microsoft JhengHei"))
base_family <- "JhengHei"
} else {
base_family <- ""
}
theme_set(
theme_minimal(base_size = 12, base_family = base_family) +
theme(
plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank()
)
)
read_sav() 讀進
PISA_tawian2022_trimmed_lab.sav。%>%
是把左邊的結果交給右邊。transmute() 只留下
ESCS。as.numeric() 拿掉 SPSS
的標籤,讓後面的平均數、分位數都用數字計算。if_else() 把
95、97、98、99 改成
NA。這份檔案裡其實沒有這些代碼,還是先處理,避免以後被當成真實分數。
最後的 cat()
印出有效人數和遺漏人數,用來確認資料有讀進來。
raw <- read_sav("PISA_tawian2022_trimmed_lab.sav")
dat <- raw %>%
transmute(
escs = if_else(ESCS %in% c(95, 97, 98, 99), NA_real_, as.numeric(ESCS))
)
cat("有效樣本:", sum(!is.na(dat$escs)),
";遺漏:", sum(is.na(dat$escs)), "\n")
## 有效樣本: 5599 ;遺漏: 0
summarise()
一次算出人數、平均數、標準差、最小最大值。全距是最大值減最小值,所以直接用同一個
summarise() 裡剛算出來的 max 和
min。中位數用
median()。quantile() 取 25% 和 75%,IQR 用
IQR(),也就是第三四分位數減第一四分位數。moments::skewness()
用來判斷分布歪不歪;偏態接近 0 表示大致對稱。across()
把表上的數字四捨五入到小數兩位,再交給 kable()。
escs_stats <- dat %>%
summarise(
人數 = sum(!is.na(escs)),
平均數 = mean(escs, na.rm = TRUE),
標準差 = sd(escs, na.rm = TRUE),
最小值 = min(escs, na.rm = TRUE),
最大值 = max(escs, na.rm = TRUE),
全距 = 最大值 - 最小值,
中位數 = median(escs, na.rm = TRUE),
Q1 = quantile(escs, 0.25, na.rm = TRUE),
Q3 = quantile(escs, 0.75, na.rm = TRUE),
IQR = IQR(escs, na.rm = TRUE),
偏態 = moments::skewness(escs, na.rm = TRUE)
)
kable(
escs_stats %>% mutate(across(where(is.numeric), \(x) round(x, 2))),
caption = "ESCS 的集中量數與變異性(小數兩位)"
)
| 人數 | 平均數 | 標準差 | 最小值 | 最大值 | 全距 | 中位數 | Q1 | Q3 | IQR | 偏態 |
|---|---|---|---|---|---|---|---|---|---|---|
| 5599 | -0.27 | 0.91 | -3.84 | 4.21 | 8.05 | -0.24 | -0.94 | 0.44 | 1.38 | -0.18 |
直方圖的 binwidth = 0.25 是每一柱寬 0.25
分。aes(y = after_stat(density)) 把縱軸改成密度,這樣才能和
geom_density()
的曲線畫在同一張圖上。兩條直線分別是平均數和中位數。盒形圖用
geom_boxplot(),盒子的高度就是 IQR。
ggplot(dat, aes(x = escs)) +
geom_histogram(
aes(y = after_stat(density)),
binwidth = 0.25,
fill = "#4C78A8",
color = "white",
boundary = 0
) +
geom_density(linewidth = 0.8, color = "#E45756") +
geom_vline(xintercept = escs_stats$平均數, linetype = "dashed", color = "#E45756") +
geom_vline(xintercept = escs_stats$中位數, linetype = "dotted", color = "#72B7B2") +
labs(
title = "ESCS 分布",
subtitle = "紅虛線 = 平均數;青點線 = 中位數",
x = "ESCS",
y = "密度"
)
ggplot(dat, aes(x = "", y = escs)) +
geom_boxplot(fill = "#4C78A8", width = 0.35, outlier.alpha = 0.35) +
labs(title = "ESCS 盒形圖", x = NULL, y = "ESCS")
有效樣本 5599 人,沒有遺漏。平均數是 -0.27,標準差是 0.91。最小值 -3.84,最大值 4.21,全距 8.05。中位數是 -0.24。中間 50% 落在 Q1 -0.94 到 Q3 0.44,IQR 是 1.38。偏態 -0.18,接近 0。
平均數和中位數很接近,直方圖是中間高、兩邊下降,所以這份資料大致對稱、略為左偏。標準差約 0.91,和 PISA 國際量尺的 1 差不多,表示臺灣樣本內部的差異並沒有特別窄。全距有 8.05,是因為兩端有離平均很遠的人;IQR 只有 1.38,代表大多數人其實集中在大約 1.4 分的範圍裡。看變異性時,全距會被極端值拉大,IQR 和標準差比較能代表中間多數人的分散程度。