初试数据分析(R)

作者: 数据蛙datafrog | 来源:发表于2017-10-02 23:11 被阅读56次

    这篇的文章主要目的是,根据提供的朝阳区医院2016年销售数据.xlsx数据表,得出月均消费次数、月均消费金额、客单价和消费趋势这五个结论。

    阅读路线:

    • 数据导入
    • 数据清洗
    • 数据分析

    数据导入

    为了方便,我把excel文件另存为了csv文件,并且重命名为2016.csv,然后放在Desktop文件夹下。

    设置工作路径

    >setwd("C:\\Users\\lkx\\Desktop")
    

    查看下到底是不是这个工作路径

    >getwd()
    [1] "C:/Users/lkx/Desktop"   #确实是的
    

    利用read.table()读入csv文件

    > import.csv<-read.table("2016.csv",header = TRUE,sep=",")
     # 其中"2016.csv"就是我们要读入的文件;header=TRUE表示读入变量(就是我们excel中见到的表头);sep=","表示以逗号为分隔符
    

    我们读取前六行先简单看一下数据

    > head(import.csv)
               购药时间    社保卡号 商品编码   商品名称 销售数量 应收金额 实收金额
    1 2016-01-01 星期五     1616528   236701 三九感冒灵        7      196   182.00
    2 2016-01-02 星期六     1616528   236701 三九感冒灵        3       84    84.00
    3 2016-01-06 星期三 10070343428   236701 三九感冒灵        3       84    73.92
    4 2016-01-11 星期一    13389528   236701 三九感冒灵        1       28    28.00
    5 2016-01-15 星期五   101554328   236701 三九感冒灵        8      224   208.00
    6 2016-01-20 星期三    13389528   236701 三九感冒灵        1       28    28.00
    

    其实我们读入的数据共有6577行,7列

    如果点击上图中箭头所指向的位置就能够看到所有的数据:

    数据处理

    当我们拿到数据的时候不应该着急去计算,先观察数据,看数据是否规整、是否符合我们的需要。根据我们的分析要求将做五个方面的修整:列名重命名、删除缺失数据、处理日期、数据类型转换和数据排序

    • 列名重命名

    把列名汉语名称变为英文状态下的名称将会编程环境更加适合。这里我们通过names()函数来重命名变量。

    >names(import.csv)<- c("time","cardno","drugld","drugName","saleNumber","virtualmoney","actualmoney")
    
    • 删除缺失数据

    在任何规模的项目中,数据都可能由于未作答问题、设备故障或误编码数据的缘故而不完整。缺失值以符号NA(Not Available,不可用)表示。函数is.na()检测缺失值是否存在的
    举例子:

    > y<-c(1,2,3,NA)
    > is.na(y)
    [1] FALSE FALSE FALSE  TRUE
    

    注意:

    1. is.na()函数是如何作用于一个对象上的,它将返回一个相同大小的对象,如果某个元素是缺失值,相应的位置将被改写为TRUE,不是缺失值的位置则为FALSE。
    2. 但是我们也应该注意到那些因为未作答问题、设备故障或错误编码数据得来的数据,不一定都是用NA来表示的,比如说因为错误得到的正无穷或负无穷都是Inf或-Inf来表示的,就需要用is.infinite()来检测了。
    3. 再者说,对于数据中某些特别怪异的值,比说在这个数据框变量销售数量中有一个值为100000000,我们看到这样的值与其他的差别如此之大,我们就可以重编码这个值为缺失值

    所以接下来我们做的处理是:

    > import.csv<-import.csv[!is.na(import.csv$time),]
    #import.cav$time  表示选取time这一列
    #is.na(import.csv$time)返回一个和import.csvs$time相同大小的对象,如果元素是缺失值,相应的位置将被改写为TRUE,不是缺失值的位置则为FASLE
    #'!'是非的意思,!is.na(import.csv$time)将和is.na(import.csv$time)是完全相反的结果
    #import.csv[!is.na(import.csv$time),]表示只要time这一列中判断条件为TRUE的对象;也即是意味着,删除time列中为缺失值的所有行。
    

    其实,我们还可以通过函数na.omit()移除所有含有缺失值的观测。 na.omit()可以删除所有含有缺失数据的行。

    • 处理日期

    我们可以看到在购药时间这一变量下的值中含有"星期五","星期六",这样的字符串,其实这些字符串对我们的分析是没有作用,所以决定把购药时间这一变量下的值进行分裂,并删除含有"星期五","星期六"这诸如此类的字符串。我们决定是使用stringr包中的str_split_fixed()函数进行分割。

    > install.packages('stringr')  #stringr安装
    > library(stringr)
    

    str_split_fixed()函数定义:str_split_fixed(string, pattern, n)
    参数列表:

    1. string: 字符串,字符串向量;
    2. pattern: 匹配的字符。
    3. n: 分割个数
    > timesplit<-str_split_fixed(import.csv$time, " ",2)
    > class(timesplit)   # 用str_split_fixed()函数分割,结果类型是matrix
    [1] "matrix"
    > import.csv$time<-timesplit[,1]
    > head(import.csv)  #检查是否分裂成功
            time      cardno drugld   drugName saleNumber virtualmoney actualmoney
    1 2016-01-01     1616528 236701 三九感冒灵          7          196      182.00
    2 2016-01-02     1616528 236701 三九感冒灵          3           84       84.00
    3 2016-01-06 10070343428 236701 三九感冒灵          3           84       73.92
    4 2016-01-11    13389528 236701 三九感冒灵          1           28       28.00
    5 2016-01-15   101554328 236701 三九感冒灵          8          224      208.00
    6 2016-01-20    13389528 236701 三九感冒灵          1           28       28.00
    

    由于import.csv$time是为字符型变量,应该转化为日期型变量。可用函数as.Date()执行这种转化。其语法为as.Date(x, "input_format"),其中x是字符型数据, input_format则给出了用于读入日期的适当格式


    > class(import.csv$time)
    [1] "character"     #字符串型
    > import.csv$time<-as.Date(import.csv$time,"%Y-%m-%d")   
    > head(import.csv)
            time      cardno drugld   drugName saleNumber virtualmoney actualmoney
    1 2016-01-01     1616528 236701 三九感冒灵          7          196      182.00
    2 2016-01-02     1616528 236701 三九感冒灵          3           84       84.00
    3 2016-01-06 10070343428 236701 三九感冒灵          3           84       73.92
    4 2016-01-11    13389528 236701 三九感冒灵          1           28       28.00
    5 2016-01-15   101554328 236701 三九感冒灵          8          224      208.00
    6 2016-01-20    13389528 236701 三九感冒灵          1           28       28.00
    > class(import.csv$time)
    [1] "Date"
    
    • 数据类型转换
    来自猴子数据分析

    为了使销售数量、应收金额、实收金额下的数据类型都为数值型,所以都做了以下的转换。

    > import.csv$saleNumber<-as.numeric(import.csv$saleNumber)
    > import.csv$virtualmoney<-as.numeric(import.csv$virtualmoney)
    > import.csv$actualmoney<-as.numeric(import.csv$actualmoney)
    
    • 数据排序
      在R中,可以使用order()函数对一个数据框进行排序。默认的排序顺序是升序。添加decreasing=TRUE时为降序即可得到降序的排序结果。
    > import.csv<-import.csv[order(import.csv$time,decreasing = TRUE),]
    > head(import.csv)
              time      cardno  drugld       drugName saleNumber virtualmoney actualmoney
    57  2016-07-19     1616528  236701 清热解毒口服液          1           28          28
    862 2016-07-19 10013306428 2367011         开博通          1           31          28
    863 2016-07-19 10030713328 2367011         开博通          4          124         118
    864 2016-07-19 10059383628 2367011         开博通          2           62          56
    865 2016-07-19   101409528 2367011         开博通          2           62          56
    866 2016-07-19    13406628 2367011         开博通          2           62          56
    

    数据分析

    • 月消费次数

    月均消费次数=总消费次数 / 月份数,并且同一天内,同一个人发生的所有消费算作一次消费。对于同一天和同一个人,我们可以认为是时间和社保卡号(暂且认为一个人使用一张社保卡)都是相同的,然后把同一人和同一天的重复项删除,即可得到总消费次数。

    > kpi1<-import.csv[!duplicated(import.csv[,c("time","cardno")]),]
    > consumernumber<-nrow(kpi1)
    > consumernumber
    [1] 5398
    

    其中,duplicated 判断对象的每个取值是否重复,如duplicated(c(1,1,2,3)) 返回 FALSE TRUE FALSE FALSE ,其中TRUE对应的为重复的值。

    判断月份数:刚刚我们关于时间的排序选择的是降序,所以时间这一序列下第一个值是最大值,最后一个值是最小值。我们用最大值减去最小值就能够得出实际天数,因为每月是30天,所以相除就能得到月数。

    > starttime<-kpi1$time[1]
    > endtime<-kpi1$time[nrow(kpi1)]
    > day<-starttime-endtime
    > month<-day%/%30
    Error in Ops.difftime(day, 30) : '%/%'对"difftime"对象不适用
    > class(day)     #查看day的类别
    [1] "difftime"
    > day<-as.numeric(day)  #转换成数值型
    > day
    [1] 200
    > month<-day%/%30   #%/% 表示取整
    > month
    [1] 6
    

    所以:月均消费次数=总消费次数 / 月份数

       > monthconsume<-consumernumber%/%month
       > monthconsume
          [1] 899
    
    • 月均消费金额

    月均消费金额=总消费金额/ 月份数,这里的总消费金额,我们选择的是实收金额的取和得来的。

    > totalmoney<-sum(import.csv$actualmoney,na.rm=TRUE)
    > monthmoney<-totalmoney/month
    > monthmoney
    [1] 50771.71
    

    原因如果实收金额中有一个缺失值的话,默认选项na.rm=FALSE会导致R函数sum返回NA,添加na.rm=TRUE就不会出错了。

    • 客单价

    客单价=总消费金额 / 总消费次数

        >pct<-totalmoney/consumernumber
        > pct
        [1] 56.43391
    
    • 消费趋势

    首先让实际消费金额按照日期(周)的分类进行求和得到下面的数据。

    > week<-tapply(import.csv$actualmoney,format(import.csv$time,"%Y-%U"),sum)
      #format(import.csv$time,"%Y-%U")表示将import.csv$time转化成这种"%Y-%U"格式
      #"Y%"表示四位数的年份,"%U"表示第多少周(一年共有52周,从第0周开始);
    #tapply(import.csv$actualmoney,format(import.csv$time,"%Y-%U"),sum)
      表示将实际消费金额按照"%Y-%U"这种日期格式进行分类并求和
    > week      #得到了这样的一组数据
     2016-00  2016-01  2016-02  2016-03  2016-04  2016-05  2016-06  2016-07  2016-08  2016-09  2016-10 
     1972.80  9679.64 10979.01  8719.73 15662.30 18758.82  3665.70  8441.51  8453.57  9988.98  8500.78 
     2016-11  2016-12  2016-13  2016-14  2016-15  2016-16  2016-17  2016-18  2016-19  2016-20  2016-21 
     9869.16 10135.23  8426.46 11400.66 14408.21 10385.33 10265.98  9496.06  9728.40 11794.11 11497.20 
     2016-22  2016-23  2016-24  2016-25  2016-26  2016-27  2016-28  2016-29 
     9530.38 10806.71 11877.43 14077.38 10894.90  8386.97 13372.67  3454.18 
    

    将把数据转换成数据框并再添加一行

    > week<-as.data.frame.table(week)   #as.data.frame.table(),这个函数我也没有弄清,自己就选择先记住了
    > week   #这是部分的数据
          Var1     Freq
    1  2016-00  1972.80
    2  2016-01  9679.64
    3  2016-02 10979.01
    4  2016-03  8719.73
    5  2016-04 15662.30
    
    > names(week)<-c("time","actualmoney")
      #names():这个函数可以返回一个向量,显示的是用做参数的类型里所有可以用"$"访问的变量名
    > week$time<-as.character(week$time)
    > week$timeNumber<-(1:nrow(week))     #添加一行
    

    开始画消费趋势图

    > plot(week$timeNumber,week$actualmoney,xlab = "时间(年份-第几周)",ylab="消费金额",xaxt="n",main="2016年朝阳区医院消费曲线",col="blue",type="b")
          #xaxt="n"就是先不显示x的刻度,通过axis函数自定义 
    > axis(1,at=week$timeNumber,labels = week$time,cex.axis=1.5)
          #1是表示你要对x轴作修改,labels就是要打的内容,
      #at就是你要多少个刻度,cex.axis=1.5表示坐标轴文字放大1.5倍
    

    总结下:月均消费次数为899,月均消费金额为50771.71,客单价为56.43391,消费趋势如下图

    通过这几天的学习明显的感觉到了制定计划的极大好处,制定计划之后自己再也不会为什么都没有学会、没有学好而感到焦灼了,而按照计划表慢慢来一步一步实现小目标,不断带来小惊喜。这里应该特别感谢猴哥,因为自己原来一直有计划无用之类的错误概念,是猴哥通过作业的方式倒逼自己做了计划。其次我们的通关都是以文章的形式来呈现,在写的过程中不知不觉的梳理清楚好多概念性问题,也是应了教是最好的学习方式这句话。感谢猴哥。

    相关文章

      网友评论

        本文标题:初试数据分析(R)

        本文链接:https://www.haomeiwen.com/subject/rfbzextx.html