如何進行python編程:一個簡單的收入波動分析模型

環境準備:sublime+ipython

打開代碼編輯器sublime——本質上,txt文本編輯器也能夠寫代碼,並保存爲以.py爲後綴的python文件,但專業的代碼編輯器能夠實現語法高亮、自動補全等功能,並支持項目管理,大大提升編寫代碼的效率和代碼的管理。所以,選擇一款合適的代碼編輯器便不可少python

打開終端並進入ipython模式——ipython能夠幫助我進行探索和試誤,利用魔術命令%paste(執行剪貼板中的python代碼)更是能夠幫助我快速查看某段代碼的執行效果app

若是說普通的代碼編輯器支持的是「編輯-編譯-運行」的工做模式,那麼ipython鼓勵的則是「執行-探索」的工做模式。編輯器

開始寫代碼

分析任務:一家電商公司的收入來自不一樣的部門,每一個部門下又有不一樣的商品類目。收入的波動來自於不一樣部門或類目的收入漲跌。爲了快速定位天天的收入波動來自哪一個部門以及哪一個類目,須要搭建模型進行自動化分析。函數

咱們的目標是利用python實現收入波動的分析模型(Analysis Model for Income Fluctuation)。
首先,咱們須要清晰定義實現最終目標的每一個步驟。工具

  1. 計算各個部門的收入變化值(觀察日收入-對比日收入)以及總體的收入變化值;excel

  2. 計算各個部門收入變化值佔比總體收入變化值的比例,取絕對值;其中,佔比最大的就是對總體收入變化影響最大的部門,能夠取經驗值10%,即佔比大於10%的部門就是對總體收入變化影響最大的部門;code

  3. 計算上述步驟獲得的影響最大的部門下每一個類目收入變化值和每一個部門的收入變化值;索引

  4. 計算每一個類目收入變化值佔比部門總體收入變化值的比例,取絕對值,找出影響最大的類目。ip

如今咱們用python來實現上述步驟:項目管理

導入所需模塊和數據:

import pandas as pd

df=pd.read_excel('/Users/xiangzhendong/Downloads/income_data.xls')

利用數據框(dataframe)的透視表(pivot_table)方法按部門聚合昨日和前日的收入數據:

df_pivot=df.pivot_table('income',index='department',columns='date',aggfunc='sum')

計算每一個部門的收入變化值以及每一個部門的變化值佔比總體變化值的比例:

df_pivot['change_amt']=df_pivot['2016-11-16']-df_pivot['2016-11-15']

df_pivot['change_pct']=abs(df_pivot['change_amt']/df_pivot['change_amt'].sum())

此時,咱們的df_pivot數據框多了change_amt和change_pct兩列。若是咱們要選出change_pct大於10%的部門,能夠這樣寫:

result=df_pivot[df_pivot['change_pct']>=0.1]

對總體變化影響最大部門已經找出來了,接下來尋找每一個部門下對部門總體變化影響最大的類目。不難發現,尋找的邏輯實際上是如出一轍的。在編寫代碼的過程當中,咱們要注意識別作事的模式,創造工具簡化同類操做。

此時,咱們能夠建立一個尋找對總體變化影響最大的成分的函數:

def max_change(df, rows):

    df_pivot=df.pivot_table('income',index=rows,columns='date',aggfunc='sum')

    df_pivot['change_amt']=df_pivot['2016-11-16']-df_pivot['2016-11-15']

    df_pivot['change_pct']=abs(df_pivot['change_amt']/df_pivot['change_amt'].sum())

    return df_pivot[df_pivot['change_pct']>=0.1]

這裏,咱們建立了max_change函數,它有兩個參數,一個是待分析的數據源(df),一個是細分項(rows),例如部門或類目。函數內部的操做與以前的代碼徹底一致。有了這個函數,咱們只要給到數據源和細分項,就能獲得影響最大的細分項。

細心的讀者必定發現這裏還有一個問題沒有解決,那就是日期:這裏日期是寫死的,並不能根據天天的日期來自動更新,顯然不符合自動化的原則。

datetime模塊能夠解決這個問題。咱們來認識下datetime如何處理日期。

In [1]: today=datetime.date.today()

In [2]: print today
2016-11-23

In [3]: today.ctime()
Out[3]: 'Wed Nov 23 00:00:00 2016'

In [4]: today.timetuple()
Out[4]: time.struct_time(tm_year=2016, tm_mon=11, tm_mday=23, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=328, tm_isdst=-1)

In [5]: today.toordinal()
Out[5]: 736291

In [6]: today.year
Out[6]: 2016

In [7]: today.month
Out[7]: 11

In [8]: today.day
Out[8]: 23

所以,今天、昨天和前天的寫法以下:

today="%s"%(datetime.date.today())

yesterday="%s"%(datetime.date.today()-datetime.timedelta(days=1))

qiantian="%s"%(datetime.date.today()-datetime.timedelta(days=2))

max_change函數也相應地寫成:

def max_change(df, rows):
    
        df_pivot=df.pivot_table('income',index=rows,columns='date',aggfunc='sum')
    
        df_pivot['change_amt']=df_pivot[qiantian]-df_pivot[yesterday]
    
        df_pivot['change_pct']=abs(df_pivot['change_amt']/df_pivot['change_amt'].sum())
    
        return df_pivot[df_pivot['change_pct']>=0.1]

若是咱們想要知道對總體影響最大的部門是什麼,能夠這樣來調用函數:

result=max_change(df, 'department')

若是咱們要知道影響最大的部門下哪一個類目影響最大,能夠這樣來調用函數:

result_lm=max_change(df[df['department']==result.index[0]],'item_cats')

result.index會返回影響最大的部門的名稱的列表,經過列表索引來引用它們。因爲有多個部門,這裏咱們須要用for循環來遍歷列表,最後將每次遍歷返回的數據框合併:

def max_lm(result,df):
    frames=[]

    for i in range(len(result)):
        result_lm=max_change(df[df['department']==result.index[i]],'item_cats')
        result_lm['department']=result.index[i]    #將部門名稱添加到數據框中
        frames.append(result_lm)
    
    return pd.concat(frames)

調用上述函數獲得每一個部門下影響最大的類目:

final=max_lm(result,df)

若是咱們想把結果導出到excel表中,能夠這樣寫:

writer=pd.ExcelWriter('output_today.xlsx')

result.to_excel(writer, sheet_name='max_departments')
final.to_excel(writer, sheet_name='max_itemcats')

writer.save()

總結

  1. 準備好python開發環境,即 「代碼編輯器+ipython」;

  2. 寫代碼前清晰定義實現最終目標的每一個步驟;

  3. 寫代碼的過程當中識別作事的模式,創造工具簡化複用性操做;

  4. 利用for循環遍歷列表。

最終代碼

import pandas as pd 
import datetime

today="%s"%(datetime.date.today())
yesterday="%s"%(datetime.date.today()-datetime.timedelta(days=1))
qiantian="%s"%(datetime.date.today()-datetime.timedelta(days=2))
print("昨天和前天的日期分別是:")
print(yesterday,qiantian)

df=pd.read_excel('/Users/xiangzhendong/Downloads/income_data.xls')

def max_change(df, rows):
    df_pivot=df.pivot_table('income',index=rows,columns='date',aggfunc='sum')
    df_pivot['change_amt']=df_pivot[yesterday]-df_pivot[qiantian]
    df_pivot['change_pct']=abs(df_pivot['change_amt']/df_pivot['change_amt'].sum())
    return df_pivot[df_pivot['change_pct']>=0.1]

result=max_change(df,'department')
print(result)

def max_lm(result,df):
    frames=[]

    for i in range(len(result)):
        result_lm=max_change(df[df['department']==result.index[i]],'itemcats')
        result_lm['department']=result.index[i]
        frames.append(result_lm)
    
    return pd.concat(frames)

final=max_lm(result, df)
print(final)

writer=pd.ExcelWriter('output_today.xlsx')

result.to_excel(writer, sheet_name='max_departments')
final.to_excel(writer, sheet_name='max_itemcats')

writer.save()
相關文章
相關標籤/搜索