學習與實踐筆記—第三講簡單數據處理

本次案例以朝陽醫院2016年的銷售數據為例,進行了數據讀取、數據預處理和數據分析的實踐。

一、數據讀取

讀取excel數據,可採用XLConnect包或openxlsx,更推薦openxlsx包,用以下代碼讀取數據

>install.packages("openxlsx")n>library("openxlsx")n>readFilePath<-"E:/朝陽醫院2016年銷售數據.xlsx"n>excelData<-read.xlsx(readFilePath,"Sheet1")n

數據導入到excelData中。

二、數據預處理

1、刪除含有缺失數據的行

數據中經常含有缺失數據,需要提前刪除以免影響分析。

na(Not Available,不可用),na.omit()可刪除所有含有缺失數據的行,但要注意如果缺失數據的行太多,則不適合。

本例採用!is.na來保留未缺失時間的數據,使用了邏輯運算非。

>excelData<-excelData[!is.na(excelData$購葯時間),] #保留未缺失時間的數據n

2、列名重命名

將初始的中文列名改成英文列名

>names(excelData)<-c("time","cardno","drugId","drugName",n "saleNumber","virtualmoney","actualmoney")n>excelDatan time cardno drugId drugNamen1 2016-01-01 星期五 001616528 861307 G降壓片(6盒/療程)n2 2016-01-03 星期日 001616528 861307 G降壓片(6盒/療程)n

3、處理日期列

將time列中的星期幾刪掉,只保留日期。此處首先需要把兩個字元串元素給分開,再選取需要的元素。採用R語言字元串處理包stringr中的str_split_fixed()來實現。以後關於字元串的處理均可使用stringr包。

> library(stringr)#載入R語言字元串處理包stringrn> timeSplit<-str_split_fixed(excelData$time," ",n=2)#將time列分成兩列n> excelData$time<-timeSplit[,1] #選取第一列n> excelDatan time cardno drugIdn1 2016-01-01 001616528 861307n2 2016-01-03 001616528 861307n

然後,將time數據從字元類型轉成時間格式的數據

> class(excelData$time)n[1] "character"n> #將字元串轉換成日期格式n> excelData$time<-as.Date(excelData$time,"%Y-%m-%d")n> class(excelData$time) #驗證得出已轉換成功n[1] "Date"n

4、數據類型轉換

為了後期計算的順利進行,需要對銷售金額、銷售次數進行數據類型轉換,轉換成數值類型。

> #將字元串轉換成數字類型n> #銷售數量n> excelData$saleNumber<-as.numeric(excelData$saleNumber)n> #應收金額(打折前金額)n> excelData$virtualmoney<-as.numeric(excelData$virtualmoney)n> #實收金額(打折後的金額)n> excelData$actualmoney<-as.numeric(excelData$actualmoney)n

採用class()函數可進行驗證。

類型的判斷與轉換採用is和as。

5、銷售數據排序

採用order()函數實現

> #數據排序order()n> #按銷售時間對數據進行降序排序n> excelData<-excelData[order(excelData$time,decreasing=FALSE),]#默認是升序n

三、數據分析

共分析月均消費次數、月均消費金額、客單價和消費趨勢四個指標。

1、月均消費次數

月均消費次數=總消費次數/月份數。其中,同一天內,同一個人發生的所有消費算作一次消費,因此要剔除重複的次數。

> kpi1<-excelData[!duplicated(excelData[,c("time","cardno")]),]n> consumeNumber<-nrow(kpi1)n

總月份數需要用最後的時間減去開始時間,再除以30取整數。

> #計算月份數n> #最小的時間值n> startTime<-kpi1$time[1]n> #最大時間值n> endTime<-kpi1$time[nrow(kpi1)]n> day<-endTime-startTimen> #月份數n> month<-as.numeric(day)%/%30 #整數除法n> class(day)n[1] "difftime"n

以上需要注意,day的格式為difftime,因此需要轉換成數字格式才能進行整數除法。

x%/%y表示,x除以y取整。

計算月均消費次數:

> monthConsume<-consumeNumber/monthn> monthConsumen[1] 899n

2、月均消費金額

月均消費金額=總消費金額/總月份,總月份已計算出,次數需要得出總消費金額。

> #月均消費金額,總消費金額/月份數n> totalmoney<-sum(excelData$actualmoney,na.rm=TRUE)n> monthmoney<-totalmoney/monthn> monthmoneyn[1] 50776.38n

sum()函數中,na.rm參數設置為TRUE,即在計算總金額時去除缺失的數據,na.rm默認是FALSE。

3、客單價

客單價=總消費金額/總消費次數,可直接計算

> #客單價,總消費金額/總消費次數n> pct<-totalmoney/consumeNumbern> pctn[1] 56.48095n

4、消費趨勢

計算每周消費金額的變化

> #計算每周的消費金額,分組函數tapplyn> weekConsume<-tapply(excelData$actualmoney,format(excelData$time,"%Y-%U"),sum)n> weekConsumen 2016-00 2016-01 2016-02 2016-03 2016-04 2016-05 2016-06 2016-07 2016-08 2016-09 n 1734.80 9639.95 10925.29 8719.73 15457.23 18518.82 3665.70 8243.47 8406.46 9939.38 n 2016-10 2016-11 2016-12 2016-13 2016-14 2016-15 2016-16 2016-17 2016-18 2016-19 n 8507.50 9829.02 10135.23 8536.40 11407.60 14559.17 10620.04 10696.94 9524.06 9728.40 n 2016-20 2016-21 2016-22 2016-23 2016-24 2016-25 2016-26 2016-27 2016-28 2016-29 n11863.40 11537.63 9558.70 10788.49 11877.43 14130.16 10894.90 8358.10 13369.76 3484.50 n

主要用到分組函數tapply(),tappy()函數中傳入了三個參數,第一個是actualmoney列,按照第二個參數format(excelData$time, "%Y-%U")的格式要求(年-周數)進行分組,第三個參數也是一個函數,即對分組後的數據用sum()函數進行計算,然後返回一個數組(array)。

另外,關於R語言當中時間的格式,%U 表示Week of the year as decimal number (00-53)

using the ?rst Sunday as day 1 of week 1,其他參考R語言的時間格式。這段tapply()函數的介紹參考了Datacruiser的學習筆記,在此感謝。

四、結果輸出與展示

使用plot()展示周消費隨時間的變化。

首先將weekConsume數據存儲到數據框中,然後對數據進行命名。通過plot()定義x軸,y軸等。最後,通過axis()定義坐標軸的顯示。

> #繪製圖形n> weekConsume<-as.data.frame.table(weekConsume)n> weekConsumen Var1 Freqn1 2016-00 1734.80n2 2016-01 9639.95n3 2016-02 10925.29n4 2016-03 8719.73n5 2016-04 15457.23n6 2016-05 18518.82n7 2016-06 3665.70n8 2016-07 8243.47n9 2016-08 8406.46n10 2016-09 9939.38n11 2016-10 8507.50n12 2016-11 9829.02n13 2016-12 10135.23n14 2016-13 8536.40n15 2016-14 11407.60n16 2016-15 14559.17n17 2016-16 10620.04n18 2016-17 10696.94n19 2016-18 9524.06n20 2016-19 9728.40n21 2016-20 11863.40n22 2016-21 11537.63n23 2016-22 9558.70n24 2016-23 10788.49n25 2016-24 11877.43n26 2016-25 14130.16n27 2016-26 10894.90n28 2016-27 8358.10n29 2016-28 13369.76n30 2016-29 3484.50n> names(weekConsume)<-c("time","actualmoney")n> class(weekConsume$time)n[1] "factor"n> weekConsume$time<-as.character(weekConsume$time)n> weekConsume$timeNumber<-c(1:nrow(weekConsume))n> plot(weekConsume$timeNumber,weekConsume$actualmoney,n+ xlab="時間(年份-第幾周)",n+ ylab="消費金額",n+ xaxt="n",n+ main="2016年朝陽醫院消費曲線",n+ col="blue",n+ type="b")n> n> axis(1,at=weekConsume$timeNumber,labels=weekConsume$time,cex.axis=1.5)n

五、總結

本次案例通過一組醫院數據,完成了數據分析的整套流程。讀取數據——數據預處理——數據分析——數據輸出,其中用到了openxlsx(),is.na,stringr,order(),duplicated(),class(),plot()等函數,使用了數據重命名、拆分列、數據格式的轉換、排序、求和、繪圖等操作。尤其要注意字元串的應用,數據計算時要進行數據格式的轉換等問題。

六、實踐

根據某城市各小區的價格數據進行練習,找出均價最高的小區。如圖所示。因為數據量太大,所以此次練習只選取了前50行。

1、數據導入

library("openxlsx")nreadFilePath<-"F:/data111.xlsx"nexcelData<-read.xlsx(readFilePath,"Sheet1")n

2、刪除空缺行

mydata<-na.omit(excelData)n

3、重命名

names(mydata)<-c("community","price","longitude","latitude")n

4、數據類型轉換

首先查看各列數據類型

> class(mydata$community)n[1] "character"n> class(mydata$price)n[1] "character"n> class(mydata$longitude)n[1] "character"n> class(mydata$latitude)n[1] "character"n

數據類型不符合要求,進行數據類型轉換

> mydata$community<-as.factor(mydata$community)n> mydata$price<-as.numeric(mydata$price)n> mydata$longitude<-as.numeric(mydata$longitude)n> mydata$latitude<-as.numeric(mydata$latitude)n

5、計算

因為數據中有小區多次重複出現,故先刪除重複行。

#剔除重複行ncommunity_price<-mydata[!duplicated(mydata[,c("community")]),]n

發現,數據由50行刪減為47行。

對各小區按照價格進行排序

> community_price<-n+ community_price[order(community_price$price),]n> community_pricen community price longitude latituden41 台鼎工業園 9888 121.3590 31.32148n33 南奉公路5幢 9911 121.4912 30.92275n25 錢橋新苑 9927 121.5454 30.87515n49 永嘉大樓 98375 121.4555 31.21105n48 滄州大樓 98456 121.4641 31.23341n47 東昌新村 98468 121.5182 31.23832n46 廣元路139弄 98554 121.4464 31.20548n45 江灣翰林 98597 121.5167 31.31222n44 興國苑 98740 121.4443 31.21541n43 復地雅園 98743 121.4973 31.22904n42 中信君廷 98859 121.4605 31.18647n40 吳興路26號 98971 121.4483 31.21203n39 浦江公館 98993 121.5059 31.22781n38 皮裘公寓 99019 121.4565 31.23356n37 梧桐花園 99027 121.4670 31.21159n36 常熟路104弄 99035 121.4542 31.22301n34 南京西路995弄 99057 121.4647 31.23525n32 潤康邨 99118 121.4721 31.23682n31 恆隴麗晶公寓 99133 121.4166 31.23902n30 華僑城 99146 121.4476 31.24612n29 王家沙花苑 99149 121.4692 31.23950n28 永嘉路525號 99150 121.4578 31.21188n27 延安西路489弄 99184 121.4441 31.22328n26 泉東小區 99197 121.5279 31.23366n24 耀江花園 99271 121.4992 31.20454n23 長陽路24弄 99290 121.5152 31.25983n22 柿子灣小區 99336 121.4354 31.19543n21 南山大樓 99353 121.4370 31.19566n20 陝西北路141弄 99494 121.4624 31.23231n19 虯江路1491號 99502 121.4710 31.25609n18 明德里 99504 121.4656 31.22900n17 富民路22弄 99531 121.4562 31.22724n16 岳陽公寓 99541 121.4595 31.21013n15 東湖公寓 99572 121.4606 31.22403n14 蓬萊路217號 99585 121.4973 31.22363n13 上海別墅 99601 121.4748 31.22537n12 鼎邦麗池(別墅) 99653 121.3791 31.20320n10 永康路124號 99700 121.4634 31.21685n9 紹興路26號 99722 121.4718 31.21619n8 太原路238號 99744 121.4620 31.21003n7 陝西南路271弄 99752 121.4691 31.21410n6 新梅泉苑 99800 121.4250 31.21129n5 天平路36弄 99807 121.4442 31.20958n4 長樂路1238號 99895 121.4474 31.22125n3 瑞金二路130號 99896 121.4723 31.21708n2 美麗園 99959 121.4456 31.22460n1 太原邸 99981 121.4624 31.20954n

均價最高的為 太原邸,均價99981元/平,均價最低的為台鼎工業園,均價 9888元/平。根據圖表中的經緯度,後期應該可以實現地圖定位輸出。

6、圖形輸出

做圖展示各小區房價。

> plot(community_price$community,community_price$price,n+ xlab="小區",n+ ylab="價格",n+ xaxt="n",n+ main="某城市小區價格",n+ type="b")n

發現x軸不能顯示各小區名稱,原因暫時未知,懷疑是數據類型的原因,因為前面的練習中輸出的圖形x軸數據均為數字類型。後面找出原因後再改進。

由圖可知,各小區均價均在10萬元附近,但有三個小區出現1萬均價。由於數據僅為部分數據,不能說明問題,所以不再做詳細討論,僅為練手。

推薦閱讀:

R中的列表(list)和數據框(data.frame)有什麼區別?
Python 在數據分析工作中的地位與 R 語言、SAS、SPSS 比較如何?
R語言 安裝完軟體後如何進行界面語言的設置?
如何用R語言畫廣東省地圖(劃分出21個地級市的邊界)?

TAG:R | R编程语言 | 数据分析工具 |