第 7 章 精緻化使用 R Markdown 和 R 代碼

在這節課當中,我們將  - 學習如何閱讀文字資料檔,而非Excel的csv檔。 - 學習如何在 R Markdown 建立美觀的表格。

7.1 讀取文字的資料檔

有些時候,題目作答的資料檔可能是以文字檔(text file)的方式來儲存,而非儲存成Excel的csv檔。當要讀取文字的資料檔時,我們可以用 “固定寬度格式 fixed width format (fwf)” 的讀取指令來讀取該資料檔。我們先從此處下載資料檔和測驗的題目。以下僅呈現該資料檔的摘錄。

                          
1 123 114 2 13131213421322
2 113 214 2 13132144342132
3 123 314 2 13131213421322
4 113 414 2 13131213421321
5 123 514 2 13131213421322
6 113 614 2 13131211213229

該資料檔記錄每位學生對13個題目的作答反應,他們的作答反應記錄在第12至第24欄的欄位。

下列的 R 指令可以讀取該資料檔,並且將學生原始作答反應用 CTT 套件的評分功能進行評分。我們還會讀取這些題目的標準答案,由於這些答案輸入成一連串的字元(characters),所以我們需要運用 R 的編碼去將這一連串的字元拆開成個別的字元,以代表個別題目的標準答案。

setwd("C:/G_MWU/ARC/Philippines/files")  #將你想要的資料夾設為當前資料夾。
d <- read.fwf("Maths13.dat", widths=c(11,rep(1,13)), stringsAsFactors = FALSE)
resp_raw <- d[,c(2:14)]
colnames(resp_raw) <- paste0("題",seq(1,13))
key <- "3131213223324" #為了簡化輸入,免除每個標準答案要加引號,所以用一連串的字元來輸入。
key <- unlist(strsplit(key,"")) #用 R 的指令將這一連串的字元拆開成個別字元。
s <- score(resp_raw,key,output.scored = TRUE) #用 CTT 評分的功能,將原始作答資料進行評分。
resp <- s$scored

請將上述的 R 編碼插入到上一節課的 R Markdown文件(6.5)中 ,並在 R Markdown 環境中產出 Maths13 的題目分析。請觀察這些分析結果,試指出哪些題目需要改善?

7.2 用中文寫 R Markdown報告的問題

用中文寫R Markdown 報告 有一些問題. 第六章(Ch6)用中文寫R Markdown 簡單的報告沒有問題.可是如果有列表標題是中文, 或是有變數是中文,報告顯示的是中文的unicode, 而不是中文字. 以下是一個 R Markdown 的例子, 畫直方圖時標題是中文.

---
title: "Test R Markdown"
author: "MWU"
date: "21/11/2021"
output: html_document
---

```{r echo=FALSE, results='hide', warning=FALSE, message=FALSE}
x <- rnorm(100)
```
用模擬方法從常態分佈隨機取100個觀察值. 下面是觀察值的分布.

```{r}
hist(x, main="常態樣本直方圖") #
```

用以上的R Markdwon 編碼產生的 html 文件 如下.

用模擬方法從常態分佈隨機取100個觀察值. 下面是觀察值的分布.

直方圖的標題是unicode, 而不是中文字.

以下是一個解決這個問題的方法. 我不知道這是否是最簡單的方法. 在 R Markdown 的header, 加一個 ctex package 的指令. 另外, 用unicode 寫直方圖的標題, 如下:

---
title: "Test R Markdown"
author: "MWU"
date: "21/11/2021"
output: html_document
header-includes:
  - \usepackage{ctex}
---

```{r echo=FALSE, results='hide', warning=FALSE, message=FALSE}
x <- rnorm(100)
```
用模擬方法從常態分佈隨機取100個觀察值. 下面是觀察值的分布.

```{r}
hist(x, main="\u5e38\u614b\u6a23\u672c\u76f4\u65b9\u5716")
```

用以上的R Markdown 產生的報告如下.

用模擬方法從常態分佈隨機取100個觀察值. 下面是觀察值的分布.

至於如何把中文字轉換成unicode, 網路上有網站可以用. 比如, Chinese Converter

7.3 進一步精緻化 R Markdown 文件R Markdown

以下是一個 分析 測驗資料的R Markdown 檔案,它能產生出更好的呈現方式,而且可以報導更詳細的結果。

---
title: "Test R Markdown"
author: "MWU"
date: "21/11/2021"
output: html_document
header-includes:
  - \usepackage{ctex}
---

```{r echo=FALSE, results='hide', warning=FALSE, message=FALSE}
rm(list=ls())
library(TAM)
library(CTT)
library(WrightMap)
library(knitr)

testname <- "Maths13"
setwd("C:/G_MWU/ARC/Philippines/files")  #將工作目錄設為你想要的資料夾。
d <- read.fwf("Maths13.dat", widths=c(11,rep(1,13)), stringsAsFactors = FALSE)
resp_raw <- d[,c(2:14)]
colnames(resp_raw) <- paste0("Item",seq(1,13))
key <- "3131213223324" #為了簡化輸入,免除每個標準答案要加引號,所以用一連串的字元來輸入。
key <- unlist(strsplit(key,"")) #用 R 的指令將這一連串的字元拆開成個別字元。
s <- score(resp_raw,key,output.scored = TRUE)
resp <- s$scored

IA <- itemAnalysis(resp)
mod1 <- tam.jml(resp)
tamDistr <- tam.ctt(resp_raw,mod1$WLE)

ItemStats <- data.frame(IA$itemReport$itemName, IA$itemReport[,c(2,3,5)], mod1$xsi)
colnames(ItemStats) <- c("\u984c\u76ee\u540d\u7a31", "\u984c\u76ee\u5e73\u5747", "\u9ede\u4e8c\u7cfb\u5217\u4fc2\u6578", "\u522a\u9664\u8a72\u984c\u5f8c\u7684\u0061\u006c\u0070\u0068\u0061\u503c", "\u0049\u0052\u0054\u0020\u96e3\u5ea6")

lowdisc <- "\u984c\u865f"
d <- which(IA$itemReport$pBis<0.2)
if(length(d)>0) lowdisc <- paste("\u984c", d)

target <- "\u9069\u4e2d"
if(mean(mod1$xsi)-mean(mod1$theta)> 0.2) target <- "\u56f0\u96e3"
if(mean(mod1$xsi)-mean(mod1$theta)< -0.2) target <- "\u5bb9\u6613"
```  

# 前言
本報告提供一個稱為\"`r testname`\" 的數學素養測驗的資料分析摘要,並藉由開源的統計軟體 R 產出分析結果(R Core Team, 2017)。本分析的目的在於鑑別該測驗哪一些是比較差的測驗題目,以及測驗的難度是否有對應到學生的能力。 

# 所分析的資料集
該資料檔共有`r nrow(resp)`位學生完成測驗的作答,該測驗工具共有`r ncol(resp)` 道測驗題目,其 CTT 信度係數為`r round(IA$alpha,2)`。

# 分析結果
以下本報告以列表的方式呈現題目分析的統計結果
```{r echo=FALSE, comment=NA, warning=FALSE, message=FALSE}
kable(ItemStats, align="ccccc", caption="\u8868\u0031\u0020\uff1a\u984c\u76ee\u7d71\u8a08\u5206\u6790\u7684\u6458\u8981 ",row.names = FALSE, digits = 3)
```  
# 題目鑑別係數
題目鑑別係數的範圍是從 `r round(min(IA$itemReport$pBis),2)` 到 `r round(max(IA$itemReport$pBis),2)`。題目鑑別度小於0.2的題號為 `r lowdisc`。

# 測驗難度是否對應到學生能力
學生在該測驗的平均能力為 `r round(mean(mod1$theta),5)` ,該測驗的題目平均難度為`r round(mean(mod1$xsi),5)`,對於作答的學生而言,該測驗難度是`r target`的。

# 能力與難度對應圖    
```{r echo=FALSE, fig.align='center'}
p <- wrightMap(mod1$WLE,mod1$xsi,item.side=itemClassic)
```  
  
# 附錄一:誘答選項分析

```{r, echo=FALSE, comment=NA, message=FALSE, warning=FALSE,results="asis"}
ctt_raw <- cbind(tamDistr[,3:7],round(tamDistr[,8:10],2))
colnames(ctt_raw) <- c("Seq","Item", "Total", "Category", "Count", "Percent", "Pbs", "MeanAbility")


for (i in 1:ncol(resp_raw)){
  itemi <- ctt_raw[ctt_raw$Item==colnames(resp_raw)[i],]
    print(kable(itemi,row.names=FALSE,align='ccccrrrr',caption="===================================================================================================="))
}
```

# 附錄二:題目特徵曲線圖

以下為各題 IRT 分析的題目特徵曲線圖: 
```{r echo=FALSE, results='hide', comment=NA, message=FALSE, warning=FALSE, fig.height = 3.5, fig.width = 6, fig.align='center'}
plot(mod1)
```  

7.4 練習

請修改上述的 Rmd 代碼以應用於以下資料集GrammarB2raw (請參考回家作業 5.4),並產出一份報告。

7.5 回家作業

請點擊此處 以下載一個關於一般能力測驗的資料集,該檔案屬於文字格式,而且學生的作答反應還沒有進行評分,請用本節課的 R Markdown 檔案對該資料檔進行分析。