我這段時(shí)間才意識(shí)到學(xué)習(xí)R的方式有點(diǎn)走錯(cuò)了,當(dāng)初想著先把介紹R的書(shū)認(rèn)認(rèn)真真從頭看一遍,或者說(shuō)把R基礎(chǔ)先學(xué)一下,但首先沒(méi)那么多時(shí)間(假的);其次書(shū)上的代碼和數(shù)據(jù)集跟我們項(xiàng)目比差別還是挺大的。
所以我覺(jué)得對(duì)于我們SP來(lái)說(shuō),最好的學(xué)習(xí)方式就是帶著問(wèn)題去學(xué)R,比如我們做項(xiàng)目,首先就是要獲取數(shù)據(jù),這也是我今天要寫(xiě)的;接著是用函數(shù)和語(yǔ)句處理數(shù)據(jù),最終輸出數(shù)據(jù)集。
處理數(shù)據(jù),包括拼接、轉(zhuǎn)換等等,這時(shí)候就存在各種各樣的問(wèn)題,SAS我們知道怎么處理了,這時(shí)候就帶著問(wèn)題,搜一下R中是怎么處理的,找到解決方法之后,最重要的就是自己敲一遍代碼,不管是學(xué)習(xí)SAS還是R都是很重要的一部分。
還有一個(gè)問(wèn)題就是現(xiàn)在項(xiàng)目中幾乎還是用SAS輸出數(shù)據(jù)集,即使你今天學(xué)會(huì)了用R處理數(shù)據(jù),但是說(shuō)不定過(guò)幾天就忘記了,所以還是要有事沒(méi)事就把項(xiàng)目的數(shù)據(jù)拿來(lái)“玩一玩”,敲一敲代碼,多敲幾遍,說(shuō)不定你就像寫(xiě)data步一樣熟悉,便記住了。
一:讀取RAW數(shù)據(jù)庫(kù)
我們做項(xiàng)目,獲取數(shù)據(jù)一般就兩個(gè)途徑,一個(gè)是EDC數(shù)據(jù),一個(gè)是讀取外部excel數(shù)據(jù)。
EDC數(shù)據(jù)我們會(huì)在SAS建立一個(gè)邏輯庫(kù)(其實(shí)也就是一個(gè)文件夾),那么在R中其實(shí)也差不多,只是不需要建立邏輯庫(kù)這么一個(gè)步驟,直接讀取文件夾下的數(shù)據(jù)集就好了,然后再加上一個(gè)將SAS數(shù)據(jù)集轉(zhuǎn)換成數(shù)據(jù)框的這么一個(gè)步驟。
在SAS中,我們是建立一個(gè)RAW 邏輯庫(kù),然后讀取RAW里面的DM發(fā)來(lái)的EDC數(shù)據(jù),比如RAW.DM;RAW.AE;RAW.CM
在R中,我們需要設(shè)立工作路徑,然后讀取路徑下的RAW數(shù)據(jù)。我拿自己課程里的SAS數(shù)據(jù)集舉例子
rm(list = ls()) #刪除一個(gè)或者多個(gè)對(duì)象
library(haven) #加載 讀取SAS數(shù)據(jù)集的一個(gè)庫(kù)
setwd("D:\\R practice\\project") #設(shè)置工作路徑,相當(dāng)如邏輯庫(kù)RAW
ae<-read_sas('ae.sas7bdat') #讀取sas數(shù)據(jù)集
ae
cm<-read_sas('cm.sas7bdat') #讀取sas數(shù)據(jù)集
cm

但是這樣存在一個(gè)問(wèn)題,項(xiàng)目中一般有幾十個(gè)RAW數(shù)據(jù)集,如果一個(gè)一個(gè)這樣寫(xiě)效率太低了,而且創(chuàng)建工作路徑之后,SAS數(shù)據(jù)集并沒(méi)有加載到R studio,所以我需要像SAS那樣創(chuàng)建一個(gè)邏輯庫(kù)之后就能訪問(wèn)所有數(shù)據(jù)集,并加載到R studio里面。所以第一想到的就是寫(xiě)個(gè)循環(huán)。
# 設(shè)置文件夾路徑
folder_path <- "D:\\R practice\\project"
# 獲取文件夾下所有 .sas7bdat 文件的文件名
sas_files <- list.files(path = folder_path, pattern = "\\.sas7bdat$", full.names = TRUE)
# 讀取每個(gè) SAS 數(shù)據(jù)集并存儲(chǔ)在列表中
#當(dāng)我們?cè)谘h(huán)處理SAS數(shù)據(jù)集時(shí),然后在循環(huán)外部直接訪問(wèn)數(shù)據(jù)集名稱時(shí),那么這些數(shù)據(jù)集確實(shí)會(huì)顯示不存在,這是因?yàn)樵谘h(huán)內(nèi)部創(chuàng)建的變量在
#循環(huán)結(jié)束后不會(huì)自動(dòng)保存到全局環(huán)境中
#所以我們可以用兩種方法,第一種是用assign函數(shù)將數(shù)據(jù)集存儲(chǔ)在全局環(huán)境中
#第二種是通過(guò)列表
#方法一
for (file in sas_files) {
sas_data <- read_sas(file)
dataset_name <- tools::file_path_sans_ext(basename(file)) # 獲取文件名(去掉路徑和拓展名)作為數(shù)據(jù)集名稱
assign(dataset_name,sas_data)
}
需要注意的是,用for循環(huán)讀取數(shù)據(jù)之后,創(chuàng)建的數(shù)據(jù)集并沒(méi)有輸出到全局環(huán)境之后,所以我們需要用assign函數(shù)加載到全局環(huán)境中去。結(jié)果如圖,可以看到RAE里面的數(shù)據(jù)現(xiàn)在都被加載到R studio里面去了,我們可以直接像SAS那樣點(diǎn)開(kāi)數(shù)據(jù)集,就能查看數(shù)據(jù)了。


可以看到,寫(xiě)了一個(gè)循環(huán)之后,相比一個(gè)一個(gè)數(shù)據(jù)集加載方便多了?,F(xiàn)在有了數(shù)據(jù),接下來(lái)就是對(duì)RAW數(shù)據(jù)集進(jìn)行處理了,這個(gè)之后的文章再講。
二:讀取外部excel數(shù)據(jù)
我們做項(xiàng)目,有時(shí)候數(shù)據(jù)可能來(lái)自外部供應(yīng)商,比如血藥濃度數(shù)據(jù),細(xì)胞因子那些,所以我們還需要知道如何用R讀取excel數(shù)據(jù)。在SAS中,用一個(gè)proc import差不多就可以,在R中,需要用到readxl庫(kù)。
讀取外部excel文件,可能會(huì)存在幾個(gè)需求:
不需要外部文件的列名
從某一行開(kāi)始讀取
3)日期讀取之后變了格式
4)需要將列名重命名成正常變量名
下面一個(gè)一個(gè)說(shuō)明,我們也不搞什么花里胡哨的技能,readxl能實(shí)現(xiàn)的功能挺多,一個(gè)一個(gè)去說(shuō)明太費(fèi)時(shí)間,也打擊學(xué)習(xí)熱情,我們有什么需求,就只解決提出需求,其余的 閑得蛋疼的時(shí)候可以繼續(xù)摸索。工作中一般就上面4個(gè)需求。
1)不需要外部文件的列名
library(readxl)
example(read_excel) #查看read_excel有什么功能及對(duì)應(yīng)的例子
testdata1 <- read_excel('D:\\R practice\\project\\test.xlsx',1)
testdata1
testdata2 <- read_excel('D:\\R practice\\project\\test.xlsx',sheet="Sheet1",col_names = FALSE)
testdata2
讀取excel的時(shí)候,你可以用sheet所在的位置,比如程序里面的1代替sheet名,也可以直接指定sheet名稱。然后如果不用文件里面的列名,可以通過(guò)選項(xiàng)col_names = FALSE實(shí)現(xiàn)。
經(jīng)測(cè)試,即使打開(kāi)了EXCEL文件,R也能正常讀取,不像SAS打開(kāi)excel文件就讀取不了了。



R自動(dòng)將列名重命名為...1 ...2 ....,而且發(fā)現(xiàn)最后一列的日期格式讀取也錯(cuò)誤了
2)從某一行讀取,可以通過(guò)skip選項(xiàng),這里我從第二行開(kāi)始讀取
testdata2 <- read_excel('D:\\R practice\\project\\test.xlsx',sheet="Sheet1",col_names = FALSE,skip=2)

發(fā)現(xiàn)從第二行開(kāi)始讀取的時(shí)候,最后一列的日期格式也展示正確了,可能R是根據(jù)第一行的格式來(lái)確定這一列展示的格式?第二列日期始終展示正確的原因是因?yàn)槲以O(shè)置了這列格式為文本,但是一般外部供應(yīng)商發(fā)過(guò)來(lái)的數(shù)據(jù)大多數(shù)時(shí)候都是不設(shè)置格式的。
3)日期讀取之后變了格式
解決辦法可以像2)一樣從某一行開(kāi)始讀取,另一種方法是讀取后用as.Date函數(shù)處理一下。
需要注意,如果你把列名讀取進(jìn)來(lái)的話,在轉(zhuǎn)換的時(shí)候會(huì)報(bào)錯(cuò),因?yàn)榈谝恍小啊焙瞬槿掌凇鞭D(zhuǎn)換不了。會(huì)報(bào)這個(gè)錯(cuò)
“Error in charToDate(x) : 字符串的格式不夠標(biāo)準(zhǔn)明確”
我們先看一下只有數(shù)字的數(shù)據(jù)怎么轉(zhuǎn)換,沒(méi)有中文名稱那一行了

testdata4 <- read_excel('D:\\R practice\\project\\test.xlsx',sheet="Sheet2",col_names = FALSE)
testdata4[[4]] <- as.Date(testdata4[[4]], origin = "1899-12-30")
excel將1900年1月1日視為第一天,但實(shí)際上它從1899年12月30日開(kāi)始計(jì)數(shù)。其實(shí)excel日期格式的數(shù)據(jù)導(dǎo)入到SAS也有一個(gè)時(shí)間差,也需要特殊處理一下。
如果還需要輸出第一行的中文列名,需要注意的是,as.date轉(zhuǎn)換的日期是數(shù)值型,但是這列在讀取進(jìn)來(lái)的時(shí)候是字符型的,所以拼在一起的時(shí)候會(huì)報(bào)上面的錯(cuò),所以還需要將數(shù)值型日期轉(zhuǎn)換成字符型。
testdata3 <- read_excel('D:\\R practice\\project\\test.xlsx',sheet="Sheet1",col_names = FALSE)
date_column <- testdata3[[4]]
# 檢查日期列的數(shù)據(jù)類型
if (is.character(date_column)) {
# 將第二行及其后的數(shù)據(jù)轉(zhuǎn)換為數(shù)字
date_column_numeric <- as.numeric(date_column[-1])
# 將數(shù)字轉(zhuǎn)換為日期格式
date_column_dates <- as.Date(date_column_numeric, origin = "1899-12-30")
# 將為日期格式轉(zhuǎn)換為字符型
date_column_dates2<-as.character(date_column_dates)
# 將轉(zhuǎn)換后的日期放回?cái)?shù)據(jù)框中
testdata3[[4]][-1] <- date_column_dates2
}


4)需要將列名重命名成正常變量名
R中重命名有好幾種方式,在SAS中應(yīng)該只有rename和在data步中創(chuàng)建新變量等于舊變量。
一種是直接使用readxl庫(kù)重命名
#重命名列名
testdata5 <- read_excel('D:\\R practice\\project\\test.xlsx',sheet="Sheet1",col_names = FALSE)
colnames(testdata5) #查看原始數(shù)據(jù)集名稱
#readxl庫(kù)
colnames(testdata5) <- c("studyid", "lbdtc", "aval","checkdate")
一種是使用#dplyr庫(kù)里的rename函數(shù)(記得提前加載dplyr到R),這時(shí)候前面的變量名是你要rename的名稱,跟SAS還不一樣。
testdata5_1 <- testdata5 %>% rename(studyid = ...1, lbdtc= ...2,aval=...3,checd=...4)

好了,上面就是用R導(dǎo)入數(shù)據(jù)的幾種方式。
祝您中秋愉快!SAS PRO竭誠(chéng)為您服務(wù)!