一篇有趣的文章

总第147篇/wupeng

这篇文章是『读者分享系列』第三篇,这一篇来自wupeng同学,这是他在读完我的书以后写的一个 Python 数据分析项目,现在他把整体的思路以及实现代码分享出来,希望对你有帮助。

这篇文章实在是太有趣了,以至于我不知道该用什么标题,所以就简单粗暴用了一篇有趣的文章这个标题。

你还可以看其他读者系列:

Python中的这几种报错你遇到过吗?

Python报表自动化

00|花园里的驱蛇者

驱使Python蟒蛇为自己工作的奇幻之旅

那是一个寻常的下午,他困了。

"飞碟瓜,最近战事紧张,多个植物花园发生了激烈的战斗,麻烦你统计一下上个月的战斗成果,看一下植物战士们的战斗力有没有提高。今天晚上向我汇报。“火炬树桩交待了这个任务,就去指挥战斗了。

"When can I leave work and go home?" 他一遍遍的问自己:“我什么时候可以下班回家?”

飞碟瓜还没有把工作做完,而这导致他目前无法下班。怎么办呢?  向日葵老师发来微信了,刚好问一下她。

后来,经过一个月的学习,飞碟瓜成为了数据分析的熟练工。他偶尔还是会想起那个令他绝望的下午。

以前,他每天的工作,就是数据的罗列,报表的生成,以及分类汇总,他曾经是植物花园里,远近闻名的”表哥”。但是,从那个下午开始,他开始尝试,把一些每月例行的重复工作,写成脚本文件,让python蟒蛇来进行办公自动化的操作。“这像是一个奇幻之旅。”飞碟瓜说。

在1996年5月20日,全世界有3000多万人使用微软Excel,而且平均每分钟新增5个用户。根据pythonanywhere.com网站博客文章的估算,世界上大约有180万至280万的python程序员。2019年2月印刷的一本《对比Excel,轻松学习Python数据分析》引起了这两个庞大的用户群体的热烈追捧。在这本书里,围绕数据分析的流程,作者数据分析师张俊红先生,详细介绍了每个步聚中,用Excel如何实现,用Python如何实现。

『 事务千万件,流程第一件。不按流程走,返工流眼泪 』。这是向日葵老师反复强调的事情,也是飞碟瓜长期工作的经验。

现在,飞碟瓜就按照数据分析的基本流程,一步步的开始分析了。

01|明确目的

根据各个花园上报的这样的明细数据

僵尸ID僵尸类别ID战场编号僵尸等级僵尸数量战斗日期战斗ID







统计战斗成果,每月例行填写下列表格:


本月累计上月同期去年同期环比同比
战功




战斗次数




每场战功




其中,战功就是僵尸等级乘以僵尸数量。打败的僵尸越多,打败的僵尸的等级越高,战功越大。

02|熟悉工具

飞碟瓜去这个网址,下载了Python蟒蛇的集成开发环境Anaconda。

然后他念起了咒语:『 天灵灵,地灵灵,Python蟒蛇快显灵。拿出熊猫工具包,日期时间包也要。帮我解决大难题,你的好处少不了 』。

Python蟒蛇回答说:『 SyntaxError: invalid character in identifier 』语法错误:标识符中的字符无效。

向日葵老师提醒道:『 你想驱使Python蟒蛇帮你干活,必须是你去学习蛇语,而不是蟒蛇学习咒语。好在蛇语不难学,跟英语挺相似的 』。

飞碟瓜无奈的打开了Anaconda里面的jupyter notebook软件,给大蟒蛇下达了指令。

from datetime import datetime
import pandas as pd

03|获取数据

飞碟瓜继续下达指令:

蟒蛇,战斗成果的原始数据文件的位置,放在了"d:\documents\temp1\"的文件夹里面,文件名字叫做"battle.xlsx"。

有一个叫做“战斗日期”的列,是记录日期的,你可不要以为是数值,你拿出你的日期时间工具包,把它处理一下,要保证理解为日期的值。

文件的编码是GBK编码的,别搞乱码了。

把文件取出之后,放在一个DataFrame数据框架里面,并且起个名字叫做data“
(DataFrame是由一组数据与一对索引(行索引和列索引)组成的表格型数据结构)

data=pd.read_excel(r'd:\documents\temp1\battle.xlsx',parse_dates=['战斗日期'],encoding='gbk')

04|熟悉数据

『 弄好了吗 』,显示dataframe的前五行数据,给我看看吧。

print (data.head())

蟒蛇回复:

  僵尸ID     僵尸类别ID  战场编号  僵尸等级  僵尸数量       战斗日期                     战斗ID
0  30006206  915000003  CDNL     4         1             2018-01-01          20170103CDLG000210052759
1  30163281  914010000  CDNL     1         2             2018-01-02          20170103CDLG000210052759
2  30200518  922000000  CDNL     2         1             2018-01-03          20170103CDLG000210052759
3  29989105  922000000  CDNL     1         3             2018-01-04          20170103CDLG000210052759
4  30179558  915000100  CDNL     4         1             2018-01-05          20170103CDLG000210052759

05|处理数据

看一下是否有缺失值,各个列的数据类型是什么

print (data.info())

蟒蛇应答:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3478 entries, 0 to 3477
Data columns (total 7 columns):
僵尸ID      3478 non-null int64
僵尸类别ID    3478 non-null int64
战场编号      3478 non-null object
僵尸等级      3478 non-null int64
僵尸数量      3478 non-null int64
战斗日期      3478 non-null datetime64[ns]
战斗ID      3478 non-null object
dtypes: datetime64[ns](1), int64(4), object(2)
memory usage: 190.3+ KB
None

飞碟瓜看了一下,注意到

  • 所有的列都是3478行,全都没有空值(non-null)

  • 而且”战斗日期"的数据格式为datetime64[ns],符合要求。

查一下是否有异常的数值,比方说,僵尸数量为负数,僵尸等级大于5,目前如果存在这类数据,就属于异常值。

print(data.describe())

蟒蛇回答:

 僵尸ID        僵尸类别ID         僵尸等级         僵尸数量
count     3.478000e+03  3.478000e+03  3478.000000  3478.000000
mean      3.004899e+07  9.214786e+08     2.526164     1.478723
std       7.303804e+04  9.653496e+06     1.109625     1.901963
min       2.998902e+07  9.100000e+08     1.000000     1.000000
25%       2.998915e+07  9.140701e+08     2.000000     1.000000
50%       3.001310e+07  9.220000e+08     3.000000     1.000000
75%       3.010167e+07  9.230000e+08     4.000000     2.000000
max       3.021483e+07  9.600000e+08     4.000000    45.000000

06|分析数据


本月累计上月同期去年同期环比同比
战功=僵尸等级*僵尸数量




战斗次数=战斗ID去重计数




每场战功=战功/战斗次数




筛选出本月累计、上月同期、去年同期 这三个时间段范围内,对应的数据框架DataFrame。

This_data=data[(data['战斗日期']>=datetime(2018,2,1))&(data['战斗日期']<=datetime(2018,2,28))]
Last_data=data[(data['战斗日期']>=datetime(2018,1,1))&(data['战斗日期']<=datetime(2018,1,31))]
Same_data=data[(data['战斗日期']>=datetime(2017,2,1))&(data['战斗日期']<=datetime(2017,2,28))]

编写函数,输入的参数为 各个时间段的数据框架DataFrame, 输出的值为 战功,战斗次数,每场战功的数据。

def get_month_data(perioddata):
    contribution=(perioddata['僵尸等级']*perioddata['僵尸数量']).sum()
    number_of_battles=perioddata['战斗ID'].drop_duplicates().count()
    s_t=(contribution/number_of_battles)
    print (contribution,number_of_battles,s_t)
    return (contribution,number_of_battles,s_t)

调用函数,计算出需要的数据

contribution_1,number_of_battles_1,a_n_1=get_month_data(This_data)   #分别计算本月的战功,战斗次数,每场战功
contribution_2,number_of_battles_2,a_n_2=get_month_data(Last_data)   #分别计算上月的战功,战斗次数,每场战功
contribution_3,number_of_battles_3,a_n_3=get_month_data(Same_data)   #分别计算上年同期的战功,战斗次数,每场战功

合并三个时间段的指标到同一个DataFrame数据框架里面

  • 设定DataFrame的行名称是['战功','战斗次数','每场战功']

  • 设定DataFrame的列名称为['本月累计','上月同期','去年同期']

  • 第1行的数据项填充为'contribution_1(本月战功),contribution_2(上月战功),contribution_3(上年同期战功)

  • 第2行的数据项填充为'number_of_battles_1(本月战斗次数),number_of_battles_2(上月战斗次数),number_of_battles_3(上年同期战斗次数)

  • 第3行的数据项填充为'a_n_1(本月每场战功),a_n_2(上月每场战功),a_n_3(上年同期每场战功)

report=pd.DataFrame([[contribution_1,contribution_2,contribution_3],[number_of_battles_1,number_of_battles_2,number_of_battles_3],[a_n_1,a_n_2,a_n_3]],columns=['本月累计','上月同期','去年同期'],index=['战功','战斗次数','每场战功'])

增加环比和同比指标。

report['环比']=report['本月累计']/report['上月同期']-1
report['同比']=report['本月累计']/report['去年同期']-1

查看数据,并且导出文件到本地。

print(report)
report.to_excel(r'd:\documents\temp1\report.xlsx')

蟒蛇回复:

       本月累计 上月同期 去年同期 环比 同比
战功     4433 4237 4331 0.046259 0.023551
战斗次数 343 315 262 0.088889 0.30916
每场战功 12.9242 13.45079 16.53053 -0.03915 -0.21816

从此以后,每当有其他的植物花园发送来战斗情况表的时候,飞碟瓜只需要召唤一下,Python蟒蛇就会刷刷刷的算好需要的数据,贴心地生成Excel文件。飞碟瓜就再也不用加班啦。

07|完整的Python代码

from datetime import datetime
import pandas as pd
data=pd.read_excel(r'd:\documents\temp1\battle.xlsx',parse_dates=['战斗日期'],encoding='gbk')
print (data.head())
print (data.info())
print(data.describe())
def get_month_data(perioddata):
    contribution=(perioddata['僵尸等级']*perioddata['僵尸数量']).sum()
    number_of_battles=perioddata['战斗ID'].drop_duplicates().count()
    s_t=(contribution/number_of_battles)
    print (contribution,number_of_battles,s_t)
    return (contribution,number_of_battles,s_t)
This_data=data[(data['战斗日期']>=datetime(2018,2,1))&(data['战斗日期']<=datetime(2018,2,28))]
Last_data=data[(data['战斗日期']>=datetime(2018,1,1))&(data['战斗日期']<=datetime(2018,1,31))]
Same_data=data[(data['战斗日期']>=datetime(2017,2,1))&(data['战斗日期']<=datetime(2017,2,28))]
contribution_1,number_of_battles_1,a_n_1=get_month_data(This_data)   #分别计算本月的战功,战斗次数,每场战功
contribution_2,number_of_battles_2,a_n_2=get_month_data(Last_data)   #分别计算上月的战功,战斗次数,每场战功
contribution_3,number_of_battles_3,a_n_3=get_month_data(Same_data)   #分别计算上年同期的战功,战斗次数,每场战功
report=pd.DataFrame([[contribution_1,contribution_2,contribution_3],[number_of_battles_1,number_of_battles_2,number_of_battles_3],[a_n_1,a_n_2,a_n_3]],columns=['本月累计','上月同期','去年同期'],index=['战功','战斗次数','每场战功'])
report['环比']=report['本月累计']/report['上月同期']-1
report['同比']=report['本月累计']/report['去年同期']-1
print(report)
report.to_excel(r'd:\documents\temp1\report.xlsx')

关于作者

领英: 

http://www.linkedin.com/in/wupeng19962000/
微信:

w13642665267

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俊红的数据分析之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值