<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    Python數(shù)據(jù)分析案例-藥店銷(xiāo)售數(shù)據(jù)分析

    共 7539字,需瀏覽 16分鐘

     ·

    2021-12-02 10:50

    最近學(xué)習(xí)了Python數(shù)據(jù)分析的一些基礎(chǔ)知識(shí),就找了一個(gè)藥品數(shù)據(jù)分析的小項(xiàng)目來(lái)練一下手。

    數(shù)據(jù)分析的目的:

    本篇文章中,假設(shè)以朝陽(yáng)醫(yī)院2018年銷(xiāo)售數(shù)據(jù)為例,目的是了解朝陽(yáng)醫(yī)院在2018年里的銷(xiāo)售情況,通過(guò)對(duì)朝陽(yáng)區(qū)醫(yī)院的藥品銷(xiāo)售數(shù)據(jù)的分析,了解朝陽(yáng)醫(yī)院的患者的月均消費(fèi)次數(shù),月均消費(fèi)金額、客單價(jià)以及消費(fèi)趨勢(shì)、需求量前幾位的藥品等。

    數(shù)據(jù)分析基本過(guò)程包括:獲取數(shù)據(jù)、數(shù)據(jù)清洗、構(gòu)建模型、數(shù)據(jù)可視化以及消費(fèi)趨勢(shì)分析。

    數(shù)據(jù)準(zhǔn)備

    數(shù)據(jù)是存在Excel中的,可以使用pandas的Excel文件讀取函數(shù)將數(shù)據(jù)讀取到內(nèi)存中,這里需要注意的是文件名和Excel中的sheet頁(yè)的名字。讀取完數(shù)據(jù)后可以對(duì)數(shù)據(jù)進(jìn)行預(yù)覽和查看一些基本信息。

    獲取數(shù)據(jù):https://pan.baidu.com/share/init?surl=tKaERGWFPycqTC1cElvc9A

    提取碼: 6xm2

    導(dǎo)入原始數(shù)據(jù)

    import numpy as np
    from pandas import Series,DataFrame
    import pandas as pd
    #導(dǎo)入數(shù)據(jù)
    file_name = '朝陽(yáng)醫(yī)院2018年銷(xiāo)售數(shù)據(jù).xlsx'
    # 使用ExcelFile()時(shí)需要傳入目標(biāo)excel文件所在路徑及文件名稱(chēng)
    xls = pd.ExcelFile(file_name)
    # 使用parse()可以根據(jù)傳入的sheet名稱(chēng)來(lái)提取對(duì)應(yīng)的表格信息
    dataDF = xls.parse('Sheet1',dtype='object')
    # 輸出前五行數(shù)據(jù)
    dataDF.head()

    # 使用sheet_names來(lái)查看當(dāng)前表格中包含的所有sheet名稱(chēng)(按順序)
    print(xls.sheet_names[0])

    查看數(shù)據(jù)基本信息:

    #查看基本信息
    #查看數(shù)據(jù)幾行幾列
    print(dataDF.shape)
    #查看索引
    print(dataDF.index)
    #查看每一列的列表頭內(nèi)容
    print(dataDF.columns)
    #查看每一列數(shù)據(jù)統(tǒng)計(jì)數(shù)目
    print(dataDF.count())

    數(shù)據(jù)清洗

    數(shù)據(jù)清洗過(guò)程包括:選擇子集、列名重命名、缺失數(shù)據(jù)處理、數(shù)據(jù)類(lèi)型轉(zhuǎn)換、數(shù)據(jù)排序及異常值處理

    (1)選擇子集

    在我們獲取到的數(shù)據(jù)中,可能數(shù)據(jù)量非常龐大,并不是每一列都有價(jià)值都需要分析,這時(shí)候就需要從整個(gè)數(shù)據(jù)中選取合適的子集進(jìn)行分析,這樣能從數(shù)據(jù)中獲取最大價(jià)值。在本次案例中不需要選取子集,暫時(shí)可以忽略這一步。

    (2)列重命名

    在數(shù)據(jù)分析過(guò)程中,有些列名和數(shù)據(jù)容易混淆或產(chǎn)生歧義,不利于數(shù)據(jù)分析,這時(shí)候需要把列名換成容易理解的名稱(chēng),可以采用rename函數(shù)實(shí)現(xiàn):

    #列重命名
    dataDF.rename(columns={<!-- -->'購(gòu)藥時(shí)間':'銷(xiāo)售時(shí)間'},inplace=True)
    dataDF.head()

    (3)缺失值處理

    獲取的數(shù)據(jù)中很有可能存在缺失值,通過(guò)查看基本信息可以推測(cè)“購(gòu)藥時(shí)間”和“社??ㄌ?hào)”這兩列存在缺失值,如果不處理這些缺失值會(huì)干擾后面的數(shù)據(jù)分析結(jié)果。 缺失數(shù)據(jù)常用的處理方式為刪除含有缺失數(shù)據(jù)的記錄或者利用算法去補(bǔ)全缺失數(shù)據(jù)。 在本次案例中為求方便,直接使用dropna函數(shù)刪除缺失數(shù)據(jù),具體如下:

    #缺失值處理
    print('刪除缺失值前:', dataDF.shape)

    # 使用info查看數(shù)據(jù)信息,
    print(dataDF.info())
    #刪除缺失值
    dataDF = dataDF.dropna(subset=['銷(xiāo)售時(shí)間','社??ㄌ?hào)'], how='any')
    print('\n刪除缺失值后',dataDF.shape)
    print(dataDF.info())

    (4)數(shù)據(jù)類(lèi)型轉(zhuǎn)換

    在導(dǎo)入數(shù)據(jù)時(shí)為了防止導(dǎo)入不進(jìn)來(lái),會(huì)強(qiáng)制所有數(shù)據(jù)都是object類(lèi)型,但實(shí)際數(shù)據(jù)分析過(guò)程中“銷(xiāo)售數(shù)量”,“應(yīng)收金額”,“實(shí)收金額”,這些列需要浮點(diǎn)型(float)數(shù)據(jù),“銷(xiāo)售時(shí)間”需要改成時(shí)間格式,因此需要對(duì)數(shù)據(jù)類(lèi)型進(jìn)行轉(zhuǎn)換。 可以使用astype()函數(shù)轉(zhuǎn)為浮點(diǎn)型數(shù)據(jù):

    #數(shù)據(jù)類(lèi)型轉(zhuǎn)換
    dataDF['銷(xiāo)售數(shù)量'] = dataDF['銷(xiāo)售數(shù)量'].astype('float')
    dataDF['應(yīng)收金額'] = dataDF['應(yīng)收金額'].astype('float')
    dataDF['實(shí)收金額'] = dataDF['實(shí)收金額'].astype('float')
    print(dataDF.dtypes)

    在“銷(xiāo)售時(shí)間”這一列數(shù)據(jù)中存在星期這樣的數(shù)據(jù),但在數(shù)據(jù)分析過(guò)程中不需要用到,因此要把銷(xiāo)售時(shí)間列中日期和星期使用split函數(shù)進(jìn)行分割,分割后的時(shí)間,返回的是Series數(shù)據(jù)類(lèi)型:

    '''
    定義函數(shù):分割銷(xiāo)售日期,提取銷(xiāo)售日期
    輸入:timeColSer 銷(xiāo)售時(shí)間這一列,Series數(shù)據(jù)類(lèi)型,例‘2018-01-01 星期五’
    輸出:分割后的時(shí)間,返回Series數(shù)據(jù)類(lèi)型,例‘2018-01-01’
    '
    ''
    def splitSaletime(timeColSer):
        timeList=[]
        
        for value in timeColSer:
            dateStr=value.split(' ')[0] #用空格進(jìn)行分割
            timeList.append(dateStr)

        timeSer=pd.Series(timeList)    #將列表轉(zhuǎn)行為一維數(shù)據(jù)Series類(lèi)型
        return timeSer

    #獲取“銷(xiāo)售時(shí)間”這一列
    timeSer = dataDF.loc[:,'銷(xiāo)售時(shí)間']

    #對(duì)字符串進(jìn)行分割,提取銷(xiāo)售日期
    dateSer = splitSaletime(timeSer)

    #修改銷(xiāo)售時(shí)間這一列的值
    dataDF.loc[:,'銷(xiāo)售時(shí)間'] = dateSer
    dataDF.head()

    '''
    數(shù)據(jù)類(lèi)型轉(zhuǎn)換:字符串轉(zhuǎn)換為日期

    把切割后的日期轉(zhuǎn)為時(shí)間格式,方便后面的數(shù)據(jù)統(tǒng)計(jì):
    '
    ''
    #errors='coerce' 如果原始數(shù)據(jù)不符合日期的格式,轉(zhuǎn)換后的值為空值NaT
    dataDF.loc[:,'銷(xiāo)售時(shí)間']=pd.to_datetime(dataDF.loc[:,'銷(xiāo)售時(shí)間'],format='%Y-%m-%d', errors='coerce')

    print(dataDF.dtypes)


    dataDF.isnull().sum()


    '''
    轉(zhuǎn)換日期過(guò)程中不符合日期格式的數(shù)值會(huì)被轉(zhuǎn)換為空值
    刪除含有NaT的空行
    '
    ''
    dataDF = dataDF.dropna(subset=['銷(xiāo)售時(shí)間','社??ㄌ?hào)'],how='any')
    datasDF = dataDF.reset_index(drop = True)
    dataDF.info()


    (5)數(shù)據(jù)排序

    此時(shí)時(shí)間是沒(méi)有按順序排列的,所以還是需要排序一下,排序之后索引會(huì)被打亂,所以也需要重置一下索引。 其中by:表示按哪一列進(jìn)行排序,ascending=True表示升序排列,ascending=False表示降序排列

    #數(shù)據(jù)排序
    dataDF = dataDF.sort_values(by='銷(xiāo)售時(shí)間', ascending=True)
    dataDF = dataDF.reset_index(drop=True)
    dataDF.head()


    (6)異常值處理

    先查看數(shù)據(jù)的描述統(tǒng)計(jì)信息

    #查看描述統(tǒng)計(jì)信息
    dataDF.describe()


    通過(guò)描述統(tǒng)計(jì)信息可以看到,“銷(xiāo)售數(shù)量”、“應(yīng)收金額”、“實(shí)收金額”這三列數(shù)據(jù)的最小值出現(xiàn)了負(fù)數(shù),這明顯不符合常理,數(shù)據(jù)中存在異常值的干擾,因此要對(duì)數(shù)據(jù)進(jìn)一步處理,以排除異常值的影響:

    #將'銷(xiāo)售數(shù)量'這一列小于0的數(shù)據(jù)排除掉
    pop = dataDF.loc[:,'銷(xiāo)售數(shù)量'] &gt; 0
    dataDF = dataDF.loc[pop,:]
    dataDF.describe()


    構(gòu)建模型及數(shù)據(jù)可視化

    數(shù)據(jù)清洗完成后,需要利用數(shù)據(jù)構(gòu)建模型(就是計(jì)算相應(yīng)的業(yè)務(wù)指標(biāo)),并用可視化的方式呈現(xiàn)結(jié)果。

    (1)業(yè)務(wù)指標(biāo)1:月均消費(fèi)次數(shù)

    月均消費(fèi)次數(shù) = 總消費(fèi)次數(shù) / 月份數(shù)(同一天內(nèi),同一個(gè)人所有消費(fèi)算作一次消費(fèi))

    #計(jì)算總消費(fèi)次數(shù)
    #刪除重復(fù)數(shù)據(jù)
    kpil_Df = dataDF.drop_duplicates(subset=['銷(xiāo)售時(shí)間','社??ㄌ?hào)'])
    totalI = kpil_Df.shape[0]
    print('總消費(fèi)次數(shù)=',totalI)

    #計(jì)算月份數(shù)
    #按銷(xiāo)售時(shí)間升序排序
    kpil_Df = kpil_Df.sort_values(by='銷(xiāo)售時(shí)間', ascending=True)
    #重命名行名
    kpil_Df = kpil_Df.reset_index(drop=True)
    #獲取時(shí)間范圍
    startTime = kpil_Df.loc[0,'銷(xiāo)售時(shí)間']
    endTime = kpil_Df.loc[totalI-1,'銷(xiāo)售時(shí)間']
    #計(jì)算月份
    #天數(shù)
    daysI = (endTime-startTime).days
    mounthI = daysI//30
    print('月份數(shù)=',mounthI)

    #月平均消費(fèi)次數(shù)
    kpil_I = totalI//mounthI
    print('業(yè)務(wù)指標(biāo)1:月均消費(fèi)次數(shù)=', kpil_I)


    (2)業(yè)務(wù)指標(biāo)2:月均消費(fèi)金額

    月均消費(fèi)金額 = 總消費(fèi)金額 / 月份數(shù)

    #消費(fèi)總金額
    totalMoneyF = dataDF.loc[:,'實(shí)收金額'].sum()
    mounthMoney = totalMoneyF // mounthI
    print('業(yè)務(wù)指標(biāo)2:月均消費(fèi)金額=', mounthMoney)


    (3)客單價(jià)

    客單價(jià) = 總消費(fèi)金額 / 總消費(fèi)次數(shù)

    #客單價(jià)
    pct = totalMoneyF / totalI
    print('業(yè)務(wù)指標(biāo)3:客單價(jià)=', pct)


    (4)消費(fèi)趨勢(shì)

    a. 導(dǎo)入python可視化相關(guān)的包

    b. 分析每天的消費(fèi)金額

    import matplotlib.pyplot as plt
    import matplotlib
    #畫(huà)圖時(shí)用于顯示中文字符
    from pylab import mpl

    mpl.rcParams['font.sans-serif'] = ['SimHei'# SimHei是黑體的意思
    #在操作之前先復(fù)制一份
    #mpl.rcParams['font.sans-serif'] = ['Songti'] # SimHei是黑體的意思
    #font = FontProperties(fname='/Library/Fonts/Songti.ttc') #設(shè)置字體
    #在操作之前先復(fù)制一份數(shù)據(jù),防止影響清洗后的數(shù)據(jù)
    groupDF = dataDF

    #將'銷(xiāo)售時(shí)間'設(shè)置為index
    groupDF.index = groupDF['銷(xiāo)售時(shí)間']
    print(groupDF.head())
    gb = groupDF.groupby(groupDF.index)
    print(gb)
    dayDF = gb.sum()
    print(dayDF)
    #畫(huà)圖
    plt.plot(dayDF['實(shí)收金額'])
    plt.title('按天消費(fèi)金額')
    plt.xlabel('時(shí)間')
    plt.ylabel('實(shí)收金額')
    plt.show()


    從結(jié)果可以看出,每天消費(fèi)總額差異較大,除了個(gè)別天出現(xiàn)比較大筆的消費(fèi),大部分人消費(fèi)情況維持在1000-2000元以?xún)?nèi)。

    c. 分析每月的消費(fèi)金額

    接下來(lái),我銷(xiāo)售時(shí)間先聚合再按月分組進(jìn)行分析:

    #將銷(xiāo)售時(shí)間聚合按月分組
    gb = groupDF.groupby(groupDF.index.month)
    print(gb)
    monthDF = gb.sum()
    print(monthDF)

    plt.plot(monthDF['實(shí)收金額'])
    plt.title('按月消費(fèi)金額')
    plt.xlabel('時(shí)間')
    plt.ylabel('實(shí)收金額')
    plt.show()


    結(jié)果顯示,7月消費(fèi)金額最少,這是因?yàn)?月份的數(shù)據(jù)不完整,所以不具參考價(jià)值。1月、4月、5月和6月的月消費(fèi)金額差異不大.  2月和3月的消費(fèi)金額迅速降低,這可能是2月和3月處于春節(jié)期間,大部分人都回家過(guò)年的原因。

    d. 分析藥品銷(xiāo)售情況

    對(duì)“商品名稱(chēng)”和“銷(xiāo)售數(shù)量”這兩列數(shù)據(jù)進(jìn)行聚合為Series形式,方便后面統(tǒng)計(jì),并按降序排序:

    #聚合統(tǒng)計(jì)各種藥品數(shù)量
    medicine = groupDF[['商品名稱(chēng)','銷(xiāo)售數(shù)量']]
    bk = medicine.groupby('商品名稱(chēng)')[['銷(xiāo)售數(shù)量']]
    re_medicine = bk.sum()

    #對(duì)銷(xiāo)售藥品數(shù)量按將序排序
    re_medicine = re_medicine.sort_values(by='銷(xiāo)售數(shù)量', ascending=False)
    re_medicine.head()


    截取銷(xiāo)售數(shù)量最多的前十種藥品,并用條形圖展示結(jié)果:

    top_medicine = re_medicine.iloc[:10,:]
    top_medicine

    # 數(shù)據(jù)可視化,用條形圖展示前十的藥品
    top_medicine.plot(kind = 'bar')
    plt.title('銷(xiāo)售前十的藥品')
    plt.xlabel('藥品')
    plt.ylabel('數(shù)量')
    plt.show()


    結(jié)論:對(duì)于銷(xiāo)售量排在前幾位的藥品,醫(yī)院應(yīng)該時(shí)刻關(guān)注,保證藥品不會(huì)短缺而影響患者。得到銷(xiāo)售數(shù)量最多的前十種藥品的信息,這些信息也會(huì)有助于加強(qiáng)醫(yī)院對(duì)藥房的管理。

    e. 每天的消費(fèi)金額分布情況

    每天的消費(fèi)金額分布情況:一橫軸為時(shí)間,縱軸為實(shí)收金額畫(huà)散點(diǎn)圖。

    # 每天消售金額 -- 散點(diǎn)圖
    plt.scatter(dataDF['銷(xiāo)售時(shí)間'],dataDF['實(shí)收金額'])
    plt.title('每天銷(xiāo)售金額')
    plt.xlabel('時(shí)間')
    plt.ylabel('實(shí)收金額')
    plt.show()


    結(jié)論:從散點(diǎn)圖可以看出,每天消費(fèi)金額在500以下的占絕大多數(shù),個(gè)別天存在消費(fèi)金額很大的情況。

    參考文章:https://www.jianshu.com/p/1becc1e5dbea




    Python“寶藏級(jí)”公眾號(hào)【Python之王】專(zhuān)注于Python領(lǐng)域,會(huì)爬蟲(chóng),數(shù)分,C++,tensorflow和Pytorch等等。

    近 2年共原創(chuàng) 100+ 篇技術(shù)文章。創(chuàng)作的精品文章系列有:

    日常收集整理了一批不錯(cuò)的 Python 學(xué)習(xí)資料,有需要的小伙可以自行免費(fèi)領(lǐng)取。

    獲取方式如下:公眾號(hào)回復(fù)資料。領(lǐng)取Python等系列筆記,項(xiàng)目,書(shū)籍,直接套上模板就可以用了。資料包含算法、python、算法小抄、力扣刷題手冊(cè)和 C++ 等學(xué)習(xí)資料!


    瀏覽 73
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評(píng)論
    圖片
    表情
    推薦
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    国产精品午夜在线观看 | 精品一区二区三区鸳鸯网 | 欧美成人91 | 三级无码在线 | 日韩黄色片视频 |