利用 Pandas 進(jìn)行簡(jiǎn)單數(shù)據(jù)分析流程

本文來自于 猴子數(shù)據(jù)分析社群的通關(guān)作業(yè)秤朗,因?yàn)檎n程是用 R 語言教的丹莲,我是用 Python 實(shí)現(xiàn)了一遍春寿,所以參考的文檔也都列了出來朗涩,總結(jié)的也挺不容易的,歡迎同學(xué)吐槽绑改。

文章主要簡(jiǎn)單實(shí)現(xiàn)了一遍初級(jí)的數(shù)據(jù)分析過程,首先是利用 pandas 讀取 excel 文件厘线,之后簡(jiǎn)單的通過去空值等過程簡(jiǎn)單處理了數(shù)據(jù)內(nèi)容识腿,最后計(jì)算了了幾個(gè)常用的業(yè)績(jī)指標(biāo)。

文章算是實(shí)現(xiàn)了一個(gè)最初級(jí)的數(shù)據(jù)分析過程造壮,比起啃一本完整的教材還是不能實(shí)踐渡讼,不如今早開始將知識(shí)投入到使用過程中,形成宏觀知識(shí)架構(gòu)方便后續(xù)補(bǔ)充學(xué)習(xí)耳璧,同時(shí)還能熟悉知識(shí)點(diǎn)和知識(shí)點(diǎn)之間的協(xié)作過程成箫。

1. 讀取 excel

# coding=utf-8

import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
file_name = "../源代碼和數(shù)據(jù)/朝陽醫(yī)院2016年銷售數(shù)據(jù).xlsx"

xls_file = pd.ExcelFile(file_name, dtype='object') # 統(tǒng)一先按照str讀入,之后轉(zhuǎn)換

table = xls_file.parse('Sheet1', dtype='object')

# file_name = "../源代碼和數(shù)據(jù)/朝陽醫(yī)院2016年銷售數(shù)據(jù).xlsx"
# table = pd.read_excel(file_name, sheeetname = 'Sheet1', dtype='object')
print type(xls_file)
print type(table)

<class 'pandas.io.excel.ExcelFile'>
<class 'pandas.core.frame.DataFrame'>

table.head()

元數(shù)據(jù)好像沒有空值,所以我自己加了兩行

2. 數(shù)據(jù)預(yù)處理

2.1 查看基本信息

print table.shape
print table.index
print table.columns

(6579, 7)
RangeIndex(start=0, stop=6579, step=1)
Index([u'購藥時(shí)間', u'社迸矢簦卡號(hào)', u'商品編碼', u'商品名稱', u'銷售數(shù)量', u'應(yīng)收金額', u'實(shí)收金額'], dtype='object')

print table.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6579 entries, 0 to 6578
Data columns (total 7 columns):
購藥時(shí)間 6577 non-null object
社痹矸罚卡號(hào) 6578 non-null object
商品編碼 6577 non-null object
商品名稱 6578 non-null object
銷售數(shù)量 6577 non-null object
應(yīng)收金額 6577 non-null object
實(shí)收金額 6577 non-null object
dtypes: object(7)
memory usage: 359.9+ KB
None

print table.count()

購藥時(shí)間 6577
社保卡號(hào) 6578
商品編碼 6577
商品名稱 6578
銷售數(shù)量 6577
應(yīng)收金額 6577
實(shí)收金額 6577
dtype: int64

2.2 列重命名

pandas 的 rename 方法 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html

col = {u'購藥時(shí)間':'time',\
u'社崩バ冢卡號(hào)':'cardno',\
u'商品編碼':'drugId',\
u'商品名稱':'drugName',\
u'銷售數(shù)量':'saleNumber',\
u'應(yīng)收金額':'virtualmoney',\
u'實(shí)收金額':'actualmoney'}
table.rename(columns = col, inplace = True)
table.head()

2.3 刪除缺失值

pandas 的 dropna 方法 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html?highlight=dropna#pandas.DataFrame.dropna|

dropna1 = table.dropna()
dropna2 = table.dropna(how = 'all') # 參數(shù)設(shè)定是明刷,所有值為 NA 才刪除掉
dropna1.head()
dropna2.head()

2.4 處理日期

# 定義一個(gè)把 time 行中日期和星期分開的函數(shù),分別返回日期和星期構(gòu)成的 list
def split_datetime_weekday(t_w_column):

datetime_list = [x.split()[0] for x in t_w_column ] # 列表推導(dǎo)式的簡(jiǎn)寫
weekday_list = [x.split()[1] for x in t_w_column]

return datetime_list, weekday_list

datetime_list, weekday_list = split_datetime_weekday(dropna1.loc[:,'time'])
dropna1.loc[:,'datetime'] = pd.to_datetime(datetime_list)
# 這里直接用了一個(gè) .to_datetime 方法满粗,將所有數(shù)據(jù)的改成了 datetime64 的類型
dropna1.loc[:, 'weekday'] = weekday_list
dropna1.info()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 6577 entries, 2 to 6578
Data columns (total 9 columns):
time 6577 non-null object
cardno 6577 non-null object
drugId 6577 non-null object
drugName 6577 non-null object
saleNumber 6577 non-null object
virtualmoney 6577 non-null object
actualmoney 6577 non-null object
datetime 6577 non-null datetime64[ns]
weekday 6577 non-null object
dtypes: datetime64ns, object(8)
memory usage: 513.8+ KB

2.5 數(shù)據(jù)類型轉(zhuǎn)換

dropna1.loc[:,'saleNumber'] = dropna1['saleNumber'].astype('float64')
dropna1.loc[:,'virtualmoney'] = dropna1['virtualmoney'].astype('float64')
dropna1.loc[:,'actualmoney'] = dropna1['actualmoney'].astype('float64')
  • 之前的改變數(shù)據(jù)類型的方式有報(bào)錯(cuò)辈末,還是改成了文檔推薦的賦值方式,兩種區(qū)別也簡(jiǎn)要寫了一下,詳細(xì)可以閱讀官方文檔

  1. 是先索引第一層級(jí)[colom1]本冲,返回了 Dataframe 的對(duì)象,然后對(duì)這個(gè)對(duì)象再次索引 [column2],所以可以看做是一種連續(xù)兩次的線性操作
  2. loc 索引則是利用了一個(gè)組合的索引劫扒,pandas 可以把這個(gè)返回對(duì)象當(dāng)做一個(gè)整體處理檬洞,同時(shí)速度上也比第一種快。
dropna1.info()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 6577 entries, 2 to 6578
Data columns (total 9 columns):
time 6577 non-null object
cardno 6577 non-null object
drugId 6577 non-null object
drugName 6577 non-null object
saleNumber 6577 non-null float64
virtualmoney 6577 non-null float64
actualmoney 6577 non-null float64
datetime 6577 non-null datetime64[ns]
weekday 6577 non-null object
dtypes: datetime64ns, float64(3), object(5)
memory usage: 513.8+ KB

2.6 排序

dropna1.sort_values("time").head(3)

3 簡(jiǎn)單數(shù)據(jù)分析

本節(jié)是對(duì)一些指標(biāo)的分析,我自己也加了一些可視化的內(nèi)容贤旷,可視化不是重點(diǎn)广料,只是簡(jiǎn)單畫了一下,并沒有做美化幼驶,甚至連標(biāo)簽都沒改艾杏。。

  • 月均消費(fèi)次數(shù)
  • 月均消費(fèi)金額
  • 客單價(jià)
  • 消費(fèi)趨勢(shì)

3.1 月均消費(fèi)次數(shù)

要點(diǎn):

  • 同一個(gè)日期和同一個(gè)社敝言澹卡號(hào)的多個(gè)消費(fèi)記錄算作一次消費(fèi)购桑,
  • 可以將單獨(dú)兩列抽出來單獨(dú)分析,先去重復(fù)氏淑,然后再計(jì)數(shù)
  • 這個(gè)分析可以畫一個(gè)每個(gè)月的消費(fèi)次數(shù)的折線圖

data_consume_unique 是將 datetime cardno 去重后復(fù)制出來的新的 Dataframe

data_consume_unique = dropna1.drop_duplicates(subset=['datetime', 'cardno']).copy(deep = True)
  • drop_duplicates 的說明 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.drop_duplicates.html 選取 datetime 和 cardno 作為篩選的子列
  • consume_time_date_ser 是將 datetime 作為 index勃蜘,構(gòu)建的 cardno 的時(shí)間序列。
  • 注:構(gòu)建時(shí)間序列的內(nèi)容一定要轉(zhuǎn)換成列表假残。我自己也是探索了半天缭贡,用 Series 的數(shù)據(jù),填充的都是 NA辉懒。
consume_time_date_ser = pd.Series(list(data_consume_unique['cardno']), index = data_consume_unique['datetime'])
# 排序之后將日期結(jié)尾 減去 日期開頭,計(jì)算總天數(shù)
date_interval = consume_time_date_ser.sort_index().index[-1]-consume_time_date_ser.sort_index().index[0]
# 利用總天使仿便,計(jì)算總月數(shù)体啰,其中 timedelta 數(shù)據(jù)類型的 attribute 參見官方文檔
# 這里用到了 days,提取出了總天數(shù)
month_count = date_interval.days/30 + 1 # 我覺得這個(gè)月份應(yīng)該是要 + 1 的嗽仪,猴子老師課程里面沒加

month_consume = consume_time_date_ser.count()/month_count
print month_consume

771

  • 通過時(shí)間序列的 month 分組荒勇,之后用 .count() 來計(jì)算組內(nèi)總和,也就是每月消費(fèi)次數(shù)
month_time = consume_time_date_ser.groupby(consume_time_date_ser.index.month).count()
plt.plot(month_time.index, month_time)
plt.show()

3.2 月均消費(fèi)金額

  • 月均消費(fèi)金額 = 總消費(fèi)金額 / 月份數(shù)
  • 這里可以畫一個(gè)每月消費(fèi)總額的柱狀圖
total_money = dropna1['actualmoney'].sum()
month_money = total_money / month_count
print month_money # 43518.6085714

43518.6085714

  • 構(gòu)建以實(shí)收金額 actualmoney 的時(shí)間序列 data_consume_actual
data_consume_actual = pd.Series(list(dropna1['actualmoney']), index = list(dropna1['datetime']))
  • 通過 month 分組,對(duì)組內(nèi)數(shù)據(jù)進(jìn)行求和闻坚,求和結(jié)果為每月的實(shí)收金額總和
month_consume = data_consume_actual.groupby(data_consume_actual.index.month).sum()
plt.plot(month_consume.index, month_consume)
plt.show()

3.3 客單價(jià)

  • 客單價(jià)(per customer transaction)是指商場(chǎng)(超市)每一個(gè)顧客平均購買商品的金額沽翔,客單價(jià)也即是平均交易金額。
consume_num = len(dropna1['cardno'].unique())
print consume_num # 所有不重復(fù)醫(yī)保卡號(hào)碼仅偎,總數(shù)量
pct = total_money / consume_num
print pct # 客單價(jià)

2426
125.568944765

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

  • 分組也是根據(jù) week 進(jìn)行的分組跨蟹,之后求和,類似于上面按照月的來求和
  • 畫出隨著 week 變化與 實(shí)收金額 actualmoney 的變化趨勢(shì)
week_consume = data_consume_actual.groupby(data_consume_actual.index.week).sum()
plt.plot(week_consume.index, week_consume)
plt.show()

這個(gè)圖還是有點(diǎn)問題的橘沥,因?yàn)殚_頭幾天還歸屬2015年的周數(shù)計(jì)算窗轩,所以信息中有53周的數(shù)據(jù),折線也就直接拉到53周了座咆。

與網(wǎng)友相關(guān)的關(guān)于切片痢艺,復(fù)制之類的討論:

歡迎關(guān)注我的微信公眾號(hào) :practice_yuyang,不定期更新數(shù)據(jù)分析學(xué)習(xí)心得介陶,學(xué)習(xí)過程堤舒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市哺呜,隨后出現(xiàn)的幾起案子舌缤,更是在濱河造成了極大的恐慌,老刑警劉巖某残,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件友驮,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡驾锰,警方通過查閱死者的電腦和手機(jī)卸留,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來椭豫,“玉大人耻瑟,你說我怎么就攤上這事∩退郑” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵裸扶,是天一觀的道長(zhǎng)框都。 經(jīng)常有香客問我,道長(zhǎng)呵晨,這世上最難降的妖魔是什么魏保? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮摸屠,結(jié)果婚禮上谓罗,老公的妹妹穿的比我還像新娘。我一直安慰自己季二,他們只是感情好檩咱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布揭措。 她就那樣靜靜地躺著,像睡著了一般刻蚯。 火紅的嫁衣襯著肌膚如雪绊含。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天炊汹,我揣著相機(jī)與錄音躬充,去河邊找鬼。 笑死兵扬,一個(gè)胖子當(dāng)著我的面吹牛麻裳,可吹牛的內(nèi)容都是我干的口蝠。 我是一名探鬼主播器钟,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼妙蔗!你這毒婦竟也來了傲霸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤眉反,失蹤者是張志新(化名)和其女友劉穎昙啄,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寸五,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梳凛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了梳杏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片韧拒。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖十性,靈堂內(nèi)的尸體忽然破棺而出叛溢,到底是詐尸還是另有隱情,我是刑警寧澤劲适,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布楷掉,位于F島的核電站,受9級(jí)特大地震影響霞势,放射性物質(zhì)發(fā)生泄漏烹植。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一愕贡、第九天 我趴在偏房一處隱蔽的房頂上張望刊橘。 院中可真熱鬧,春花似錦颂鸿、人聲如沸促绵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽败晴。三九已至浓冒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間尖坤,已是汗流浹背稳懒。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留慢味,地道東北人场梆。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像纯路,于是被迫代替她去往敵國(guó)和親或油。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容