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

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

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

文章算是實現(xiàn)了一個最初級的數(shù)據(jù)分析過程,比起啃一本完整的教材還是不能實踐,不如今早開始將知識投入到使用過程中,形成宏觀知識架構(gòu)方便后續(xù)補充學(xué)習(xí),同時還能熟悉知識點和知識點之間的協(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'購藥時間', u'社??ㄌ?, u'商品編碼', u'商品名稱', u'銷售數(shù)量', u'應(yīng)收金額', u'實收金額'], dtype='object')

print table.info()

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

print table.count()

購藥時間 6577
社??ㄌ?6578
商品編碼 6577
商品名稱 6578
銷售數(shù)量 6577
應(yīng)收金額 6577
實收金額 6577
dtype: int64

2.2 列重命名

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

col = {u'購藥時間':'time',\
u'社??ㄌ?:'cardno',\
u'商品編碼':'drugId',\
u'商品名稱':'drugName',\
u'銷售數(shù)量':'saleNumber',\
u'應(yīng)收金額':'virtualmoney',\
u'實收金額':'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 處理日期

# 定義一個把 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)式的簡寫
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)
# 這里直接用了一個 .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ù)類型的方式有報錯,還是改成了文檔推薦的賦值方式,兩種區(qū)別也簡要寫了一下,詳細可以閱讀官方文檔

  1. 是先索引第一層級[colom1],返回了 Dataframe 的對象,然后對這個對象再次索引 [column2],所以可以看做是一種連續(xù)兩次的線性操作
  2. loc 索引則是利用了一個組合的索引,pandas 可以把這個返回對象當(dāng)做一個整體處理,同時速度上也比第一種快。
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 簡單數(shù)據(jù)分析

本節(jié)是對一些指標的分析,我自己也加了一些可視化的內(nèi)容,可視化不是重點,只是簡單畫了一下,并沒有做美化,甚至連標簽都沒改。。

  • 月均消費次數(shù)
  • 月均消費金額
  • 客單價
  • 消費趨勢

3.1 月均消費次數(shù)

要點:

  • 同一個日期和同一個社??ㄌ柕亩鄠€消費記錄算作一次消費,
  • 可以將單獨兩列抽出來單獨分析,先去重復(fù),然后再計數(shù)
  • 這個分析可以畫一個每個月的消費次數(shù)的折線圖

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

data_consume_unique = dropna1.drop_duplicates(subset=['datetime', 'cardno']).copy(deep = True)
consume_time_date_ser = pd.Series(list(data_consume_unique['cardno']), index = data_consume_unique['datetime'])
# 排序之后將日期結(jié)尾 減去 日期開頭,計算總天數(shù)
date_interval = consume_time_date_ser.sort_index().index[-1]-consume_time_date_ser.sort_index().index[0]
# 利用總天使,計算總月數(shù),其中 timedelta 數(shù)據(jù)類型的 attribute 參見官方文檔
# 這里用到了 days,提取出了總天數(shù)
month_count = date_interval.days/30 + 1 # 我覺得這個月份應(yīng)該是要 + 1 的,猴子老師課程里面沒加

month_consume = consume_time_date_ser.count()/month_count
print month_consume

771

  • 通過時間序列的 month 分組,之后用 .count() 來計算組內(nè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 月均消費金額

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

43518.6085714

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

3.3 客單價

  • 客單價(per customer transaction)是指商場(超市)每一個顧客平均購買商品的金額,客單價也即是平均交易金額。
consume_num = len(dropna1['cardno'].unique())
print consume_num # 所有不重復(fù)醫(yī)??ㄌ柎a,總數(shù)量
pct = total_money / consume_num
print pct # 客單價

2426
125.568944765

3.4 消費趨勢

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

這個圖還是有點問題的,因為開頭幾天還歸屬2015年的周數(shù)計算,所以信息中有53周的數(shù)據(jù),折線也就直接拉到53周了。

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容