寧波市疾病預防控制中心(315010) 紀 威 張 濤 崔 軍
寧波市慢性病監(jiān)測工作覆蓋了四類主要慢性病——糖尿病、冠心病急性事件、腦卒中和惡性腫瘤的監(jiān)測,該工作自2002年的監(jiān)測點醫(yī)院到2006年的省衛(wèi)生監(jiān)測區(qū),再至2009年慢性病網(wǎng)絡直報在全市醫(yī)療機構開展,隨著慢病患者逐年增多,發(fā)病報告數(shù)據(jù)也日益增長,因此如何對大量慢性病監(jiān)測數(shù)據(jù)進行快速、準確、有效地審核管理也成為困擾疾病預防控制機構的一個亟待解決的難題。筆者以寧波市慢病監(jiān)測數(shù)據(jù)為例,應用R軟件,提供一種簡便的方式完成監(jiān)測數(shù)據(jù)的清理和統(tǒng)計工作,為更多監(jiān)測工作者提供了新的工作方法,也為R軟件的應用提供了新思路。
R軟件像SAS和Stata等軟件一樣,主要使用命令行的方式處理數(shù)據(jù),語法簡潔靈活、軟件開源是R諸多亮點中的一粟?,F(xiàn)在主流的數(shù)據(jù)庫以及數(shù)據(jù)分析軟件都可以方便地和R軟件實現(xiàn)對接和互調,R也可以調用C、Java等高級語言,還可以根據(jù)使用者的需要定制擴展包以完成特定的工作。
1.數(shù)據(jù)讀入
監(jiān)測中常見的為csv和Excel文件,其中csv是逗號分割分文本文件,可以通過
dat <- read.csv("文件路徑/文件名.csv")方式讀入并存儲在數(shù)據(jù)集dat中以便調用。例如筆者有名為“tnb330200.csv”的文件存放在E盤下,則使用
dat <- read.csv("E:/tnb330200.csv",as.is = TRUE)
其中read.csv是R中的一個函數(shù),用于讀入csv文件,as.is是這個函數(shù)中的一個選項,用于防止在數(shù)據(jù)讀入時字符變量向因子類型的自動轉換。
若數(shù)據(jù)為Excel文件,筆者推薦的方式是使用RODBC功能包中的odbcConnectExcel和sqlFetch函數(shù)。類似的,該包還提供了Access等數(shù)據(jù)文件的odbc接口。以E盤下的tnb330200.xls為例,使用方式如下:
require(RODBC)
chl <- odbcConnectExcel("E:/tnb330200.xls")
dat <- sqlFetch(chl,"Sheet1",as.is = TRUE)
odbcClose(chl)
require為加載包的命令,odbcConnectExcel建立與chl與Excel文件間的連接,sqlFetch讀取Excel文件中名為"Sheet1"的表格并存儲在數(shù)據(jù)集dat中,最后關閉這個連接。
在實際工作中,讀入的數(shù)據(jù)往往比較復雜,比如觀測個案可能含有缺失等情況,通常情況下對于缺失處為空的情況R會自動將字符型的空白處理為空字符,而將數(shù)值型的空白處理為NA,“NA”是R中表示缺失的字符,可以用is.na來判斷。如果用戶在錄入數(shù)據(jù)時,使用其他值例(如“9”“99”和“999”等)來代表缺失,則可以在讀入數(shù)據(jù)時使用參數(shù)na.strings=c(9,99,999)來指定缺失,也可以在數(shù)據(jù)讀入后將包含這些字符的位置替換為NA即可,替換方法可以參考本文的相關段落。
有時一個觀測可能占據(jù)多行,變量值中有可能包含分隔符等,對于前者,通??梢栽跀?shù)據(jù)讀入后使用專門的數(shù)據(jù)整理函數(shù)(例如reshape2包中的相關函數(shù))進行處理;而對于后者,通??梢栽谧x入函數(shù)中使用相應的參數(shù)加以解決,有興趣的讀者可以閱讀幫助文件和相關的文獻。
2.查找重復個案
糖尿病數(shù)據(jù)中包含患者的很多信息,例如姓名、性別、身份證號碼等,由于存在同一患者多次報告的情況,因此在分析前對數(shù)據(jù)進行查重是有必要的。查重主要使用duplicated函數(shù),假設糖尿病數(shù)據(jù)存儲在數(shù)據(jù)集dat中,假定姓名、性別、身份證號碼、住址、診斷名稱都相同的為重復個案,則找出這些重復個案可以使用如下方式:
dat[with(dat,duplicated(姓名,性別,身份證號碼,街道,糖尿病類型)),]
with函數(shù)指定所要操作的數(shù)據(jù)集,duplicated函數(shù)指定用于識別重復的變量名稱。相應地,如果需要在數(shù)據(jù)集中刪除這些重復個案,只需使用:
dat[-with(dat,duplicated(姓名,性別,身份證號碼,街道,糖尿病類型)),]
3.查找含有缺失的個案
在慢性病報告中,個案信息的收集通常情況下是不完全的,有些重要信息(如身份證號碼、電話等)的缺失會對監(jiān)測查重和隨訪工作的順利進行有較大影響,所以找出這些信息缺失的個案也顯得尤為重要,假設個案信息存儲在數(shù)據(jù)集dat中,則找出身份證號碼和電話缺失的個案可以使用如下方法:
dat[ind_idmiss | ind_phmiss,]
身份證號碼中通常會出現(xiàn)空格和空字符,所以需要先將空格替換為缺失值NA,再來查找缺失個案;電話號碼中除空格外還可能用“無”“未留”來表示缺失,因此需將包含該字的也替換為NA;is.na函數(shù)用于判斷一個字段中是否為NA值(即缺失值),這樣就獲得了身份證號碼和電話缺失的個案記錄,監(jiān)測工作者可以在此基礎上將相關信息予以補充。
4.查找數(shù)據(jù)中的邏輯錯誤
對數(shù)據(jù)進行邏輯審核是數(shù)據(jù)清洗中的重要一環(huán),找出有邏輯錯誤的個案并及時訂正是保證數(shù)據(jù)質量的重要手段,使用R軟件可以用簡潔的語句找出邏輯錯誤,以寧波市惡性腫瘤監(jiān)測數(shù)據(jù)為例,通常有如下邏輯錯誤:錄入日期早于報卡日期、出生日期與身份證號碼中的信息不符、男性診斷有女性疾病(如宮頸癌)、女性診斷有男性疾病等,這里我們假設腫瘤存儲在數(shù)據(jù)集dat中,則找出這些個案可以使用如下方式:
attach(dat)
ind1 <- 錄入日期 < 報卡日期
ind2 <- substr(身份證號碼,7,14) != gsub("-","",出生日期)
#出生日期格式為"1966-01-01"
ind3 <- 腫瘤分類 == "宮頸癌" & 性別 == "男"
ind4 <- 腫瘤分類 == "前列腺癌" & 性別 == "女"
dat_logi <- dat[ind1 | ind2 | ind3 | ind4,]
detach(dat)
attach函數(shù)通常用于簡化程序的書寫,其作用是將數(shù)據(jù)集dat加載到R的搜索路徑中,加載后只需輸入該數(shù)據(jù)集中的變量名稱即可直接調用這個變量;substr函數(shù)取出身份證號碼中生日所在的8位數(shù)字,gsub替換掉出生日期的橫線"-",然后將包含這4種邏輯錯誤的個案統(tǒng)一存儲在數(shù)據(jù)集dat_logi中,最后detach從R的搜索路徑中卸載數(shù)據(jù)集dat。
5.將有邏輯錯誤的個案寫入到文件
當找出含有邏輯錯誤的個案后,需要對個案進行逐一核對以訂正錯誤,此時通常需要將數(shù)據(jù)寫入到R之外以便核對,將數(shù)據(jù)集寫入文件(以csv文件為例)可以使用:
write.csv(dat_logi,"E:/含有邏輯錯誤的個案.csv",row.names = FALSE)
其中文件被寫到E盤下名為“含有邏輯錯誤的個案”的csv文件,選項row.names = FALSE表示在寫入時不要寫入R自動生成的個案行名。
本文中寥寥十幾行程序就完成了基本的數(shù)據(jù)查重和邏輯審核工作,R語言的簡潔可見一斑,而且R語言中的函數(shù)使用簡單直觀,便于使用者理解掌握。
此外,由于R軟件優(yōu)秀的可定制性,使用者可以編寫自己的軟件包以解決特定的問題,筆者便在本文的基礎上編制了專門用于慢性病數(shù)據(jù)清理和統(tǒng)計的軟件包mbpkg,使用者可以不需要任何編程基礎,只需簡單地鼠標點選便可輕松完成更為復雜的慢性病數(shù)據(jù)審核管理工作,在實際工作和科研過程中都有較好的推廣意義。有興趣的讀者可以根據(jù)研究內容編寫自己的軟件包。
參 考 文 獻
1. Brian Ripley.ODBC Connectivity.Department of Statistics,University of Oxford,2012,16:17.
2.Venables WN,Smith DM,the R Core Team.An Introduction to R,2012:27-28.