编程语言应用

首页 » 常识 » 预防 » 学生分享巧用Python管理企业
TUhjnbcbe - 2023/3/19 19:03:00

大家好,很高兴能够认识大家,和大家分享我的故事。

我自大学毕业进入工作岗位已近七年,目前从事管理岗位,日常工作庞大繁杂,涉及公司管理制度的策划与执行、部门汇报材料的编制、管理数据的收集与分析、专业考核的实施、日常报表的汇总与填写等等事宜,一直以来,我都被繁重的工作压得喘不过气来。

我最初接触Python,去年8月份我开始了编程基础课的学习,后来又慢慢接触了爬虫、数据分析和办公自动化等课程。

自接触Python至今已经大半年,其过程也是历尽千辛万苦。上大学的时候,C语言是我们的必修课之一,但是课上听得只想睡觉,课程过了之后再也没碰过。那个时候学编程原因无非这几个:必修课必须要过、考二级证。至于这门语言有什么用,我不知道也没人告诉我。而现在学习Python就不一样了,目标非常明确,因此虽然中间的学习过程也遭遇了各种困难,尤其是在“面向对象”之后的课程理解起来都有点难度,但是还是咬咬牙坚持下来了。

个人的意志力非常重要。最早接触其实是从“扇贝单词”开始的,那个时候因为工作需求,想练练英语,就在搜“免费而且好用的背单词软件”,我还特意都下下来试了试,中间有段时间特别沉迷某款手游,而且已经影响到我和家人之间的关系,平时也经常熬夜,在一次与家人的争吵中我觉得,这不是我想要的生活。我卸载了游戏,坚持学习英语,坚持运动健身,坚持学编程,过着自律而充实的生活。一旦一个人选择了成长,虽然路途艰辛,但那种感受到每天看到的世界都不同的感觉,是真正让人能体会到快乐的。

探索:从交通违章记分到公司管理制度的联想

回归Python,我学习的主要需求是办公自动化,而且我擅长的领域主要是数据分析,除了根据*帮主的指导进行课程学习之外,我还会按照自己的需求进行一些编程的尝试。

下面给大家提供一个案例,这个py小程序编写就是为了减少平时工作量的,因为涉及到公司的信息,所以我对它进行了调整,其中的制度条款也尽可能地简化(实际公司在管理过程中,所面对的情况要复杂的多,但对于Python程序编写上是不会有太大影响的,唯一影响就是会增加数据运算量,数据读取和处理速度会相应减慢)。

交通违章记分制度相信大家都不陌生,记分某种层面上比违章罚款还要命,每位司机每年有12分,扣完后还会有各种繁琐的流程等着你。这个制度的高明之处在于:

第一,扣分制度与罚款存在很大的不同,罚款主要作用在于惩戒,罚完很多人可能就“好了伤疤忘了疼”,但是扣分不一样,你扣的分在这一周期里不会消失,你违章越多,到后边你越不敢违章;

第二,违章扣分更加人性化,满12分后吊销驾照属于惩罚措施,前边没满12分的时候仅仅能算作一种警告。大家可能就会问了,交通违章不是也要罚款的吗?

这里一定要理解到位,这里的对违章的经济处罚是“罚款”制度,而非记分制度。

到这里大家可能会联想到,记分制度若能成为企业的一种管理制度,而且如果能与罚款制度相剥离开来,很可能会产生很多意想不到的效果。

我用Python把这个联想实践了一下,大致内容如下:假设甲公司为一个大型物流公司,因为公司内物流场地车辆繁多,而且里面大多为雇佣分包单位的司机,因为对厂内规章制度不熟悉,经常违章驾驶,甚至会出现伤人、撞物的情况。由于交警不会按照交通法规去干涉公司内部的事情,所以甲公司参考交通法律法规,做了一个场地内的记分制度,该制度非常简单,有以下几个特点:

1、司机违章则扣分,扣完12分就取消场内作业的资格;

2、有12分、6分、3分、2分、1分,共五个扣分等级;

3、该公司按照作业工艺不同,共划分三个区域(东区、中区、西区),三个区域分别设立专人维持交通秩序并对违章人员开具罚单,并都有自己独有的违章单编号规则。

思考:数据观察与需求分析

现在我们思考一下我们的数据分析需求:

第一,肯定是要看哪些人12分被扣完了,这是我们这个制度的核心所在。

第二,刚刚推出这个制度的时候,各单位一定会因为增加了工作量而产生抵触情绪,我们也不想通过考核、罚款等过于激烈的方式推动制度实行,于是我们想到了会议通报的方式,看看哪个单位执行度好一点。

第三,因为司机都是分包单位委派的,我们要明确司机属于哪个分包单位。

第四,很多时候违章的背后不光是司机的问题,可能还有其它潜在的因素,比如道路设计不合理、路上障碍较多。如果是公司本身存在的问题,我们要采取措施进行改善。

好了,明白需求了,我们再来看看这三个单位提交上来的表格是怎样的(表格格式是固定的,但是有时候也会填得乱七八糟),这里人员姓名我是从百家姓里复制过来的,所以不会有重名,但是实际上一个企业里面经常会有重名问题。请思考,对于这种情况应该怎么处理呢?

很简单,我们可以将身份证号或者员工编号作为唯一识别标识。

△由于篇幅问题只展现部分人员

整体填得还行,那我们开始设计目标数据表格。大体分为3个表格:

△设计的表格模板

01规划:程序设计的整体架构

好了,到这里我们可以设计程序了。要处理数据,而且需要调用excel,所以首选pandas库。要处理excel的写入、读取,需要openpyxl、xlwtxlwt、xlwigns。这里面根据习惯选用,我比较喜欢xlwings,一是因为它对xlxs和xlx两种格式都完美支持,另一方面是它支持excel批量处理。

Importpandasaspdimportxlwingsasxw整体架构大体上是这样的:classTraffic_Violation_Analyse:def__init__(self):path=r‘最初表格.xlsx’Vio_file=pd.read_excel(path)#文件读取self.File_creat()#创建文件(注意此处函数调用需加self)self.Zone_analyse()#按区域分析self.Contractor_analyse()#按照分包商扣分情况分析self.Blacklist()#看看谁扣满12分了self.File_write_in()#文件写入

具体效果如下,整个代码的骨架就出来了,非常合理、非常的人性化。

正片:拆分任务,解决问题

好了,正片开始,编程的核心不在于代码,而在于如何拆分任务,然后逐步解决问题:

l第一部分

第一部分比较简单,就是单纯创建文件。我们要创建一个workbook,并在里面置入三个sheet,分别为“区域违章分析”、“分包商违章分析”、“吊销场内运输司机名单”。代码如下:

defFile_creat(self)#创建文件app=xw.App(visible=True,add_book=False)workbook=app.books.add()Sheets_name=[01区域违章分析,02分包商违章分析,03吊销场内运输司机名单]foriinrange(3):sheet=workbook.sheets.add(Sheets_name)workbook.save(r’(此处填写欲保存路径)’)workbook.close()app.quit()

l第二部分

然后进入第二部分,按照区域进行违章分析。这部分的处理是需要一点点技巧的,首先我们需要观察哪里可以获取“区域划分”这个信息。

从直观的表格内容来看,我们是没有办法区分“区域”的,但是我们再进一步观察可以发现,里面有“交通违章单号”一列,我们发现他们的命名规则统一都是“******--****”,“”前的部分为4位到6位的字符串,不难发现,他们和区域是存在对应关系的。事实上你会发现,我们如果进行管理,不给下属单位制订编号规则,它们的命名规则也往往非常具有规律性(所以说程序员眼中的世界和一般人眼中的世界是两个完全不同的世界):

West西区DongQu东区ZQGLB根据排除法,只能是中区(事实上它的意思是“中区管理部”)

因为加入了数据的转换,我们需要在原有框架下再加入一个函数:

defviolation_tickets_convert(self,tickets_data)

这种一一对应的方式,用字典来处理极为适合,该案例中,通过“交通违章单号”这列每个数据的前四个字母进行判断,如果为West就是西区,如果是Dong就是东区,如果是ZQGL就是中区,我们需要在__init__里加入以下转换代码:

classTraffic_Violation_Analyse:def__init__(self):Path=r‘(此处填写文件路径)’Vio_file=pd.read_excel(path)#文件读取dep_send=[]#建立空列表,将Vio_file里的“交通违章单号”列转换为部门名后形成Seriesfortickets_datainself.data_base[交通违章单号]:dep_send.append(self.violation_tickets_convert(tickets_data))#调用函数将“交通违章单号”转换为部门名self.violation_tickets_convert(tickets_data)self.File_creat()#创建文件(注意此处函数调用需加self)self.Zone_analyse()#按区域分析self.Contractor_analyse()#按照分包商扣分情况分析self.Blacklist()#看看谁扣满12分了self.File_write_in()#文件写入

现在我们来编写violation_tickets_convert函数:

defviolation_tickets_convert(self,tickets_data):#提取违章编号前四位self.four_letters=tickets_data[:4]#违章单号编码前四位所对应的单位self.dep_code={#违章单号前四位与区域对应情况Dong:东区,ZQGL:中区,West:西区}ifself.four_lettersinself.dep_code:#如果违章单号的前四位出现在字典的index里sending_dep=self.dep_code[self.four_letters]#知识点:利用字典的index查找字典的valuereturnsending_depelse:#如果违章单号的前四位没有出现在字典的index里sending_dep=error#明显填报有误,赋值为errorreturnsending_dep

这一部分在整个代码中算是相对比较技巧性的一部分了,这部分搞定了,剩下的只需要套公式一般慢慢完成代码即可。

l第三部分

接下来按照区域分析。

分组计算最常用的方法是groupby函数,这里也可以使用这个函数。大家可以试试这个代码:

defZone_analyse(self):self.Zone_analyse=self.Vio_file.groupby([违章发出单位,本次违章扣分]).count().Tself.West=self.Zone_analyse.西区print(self.West)

这里不打算细讲这个,因为这种方法后续还有很多细节需要处理,比如说列序的调整,比如对columns的重命名,还是比较麻烦的,对于刚接触Python的同学而言,也容易导致思路混乱,因此我用的是最简单粗暴的方法:直接创建目标函数的DataFrame,再一个个往里填,再看看我们的需求表格:

好了,我们来设计这个DataFrame:

dep_name=[东区’,中区’,西区’,合计]#这个作为indexrank=[12分单数,6分单数,3分单数,2分单数,1分单数]#这个作为columns

然后往里面一行一行地填入数值,基本思路就是用pandas的筛选功能选出符合条件的值,再用len函数求出数量,以东区为例,代码如下:

东区_12分=len(self.Vio_file[(self.Vio_file[违章发出单位]==东区)(self.Vio_file[本次违章扣分]==12)])东区_6分=len(self.Vio_file[(self.Vio_file[违章发出单位]==东区)(self.Vio_file[本次违章扣分]==6)])东区_3分=len(self.Vio_file[(self.Vio_file[违章发出单位]==东区)(self.Vio_file[本次违章扣分]==3)])东区_2分=len(self.Vio_file[(self.Vio_file[违章发出单位]==东区)(self.Vio_file[本次违章扣分]==2)])东区_1分=len(self.Vio_file[(self.Vio_file[违章发出单位]==东区)(self.Vio_file[本次违章扣分]==1)])

再复制粘贴两次,把代码中的区域更改成中区与西区即可。最后再建立DataFrame:

self.dep_analyse=pd.DataFrame([[东区_12分,东区_6分,东区_3分,东区_2分,东区_1分],[中区_12分,中区_6分,中区_3分,中区_2分,中区_1分],[西区_12分,西区_6分,西区_3分,西区_2分,西区_1分]],index=dep_name,columns=rank)

在Python中代码实际上是这个样子的,可以看出整体还是比较好阅读的,代码相对还是比较有条理的。

运行一下看看。

我们想要的已经有了,剩下就是横向和纵向两个求和了,也就是标*区域。

思路也很简单,先是横向求和。横向求和的不是简单的相加就可以,因为前边的数都是单数,需要注意总记分是“对应分值*该分值的单数”再求和,即:

self.dep_analyse[总计分]=self.dep_analyse[12分单数]*12+self.dep_analyse[6分单数]*6+self.dep_analyse[3分单数]*3+self.dep_analyse[2分单数]*2+self.dep_analyse[1分单数]*1

然后是纵向求和。这个比较简单,直接上边各行相加就行了,有两个思路:

第一个思路,直接用loc方式把上面几行加起来:

self.dep_analyse.loc[合计]=self.dep_analyse.loc[东区]+self.dep_analyse.loc[中区]+self.dep_analyse.loc[西区]

结果如下:

第二个思路,使用apply函数:

self.dep_analyse.loc[合计]=self.dep_analyse[[12分单数,6分单数,3分单数,2分单数,1分单数,总计分]].apply(lambdax:sum(x))

结果如下:

推荐第二种,因为该案例为了方便演示,所以分区进行了极大的简化,如果区域数超过10个,代码将会变得非常臃肿。

好了,这个函数就完成了。

l第四部分

是对分包商的违章情况进行分析。

先来看一下需求与原数据:

看完表格的瞬间,我们就有了灵感,首先我们需求表格的第一列是按分包商名称分类的,所以groupby函数是最佳选择,然后我们要分析每个分包商的违章单数和扣分总数,单数就是数一数挂在这个分包单位名下的“交通违章单号”出现了几次,对应count()函数,扣分总数就是把B列求和,对应sum()函数,现在要把两列的运算整合起来,要用到agg函数,于是:

contractor_database=self.Vio_file.groupby(所属单位).agg({交通违章单号:lambdax:len(x),本次违章扣分:lambdax:sum(x)})print(contractor_database)

结果出来了:

基本上就是我们想要的,我们只需要用rename函数重命名一下columns就可以了:

contractor_database.rename(columns={交通违章单号:违章次数,本次违章扣分:扣分总数},inplace=True)

l第五部分

让我瞧瞧谁扣满12分了。这部分也比较简单,说白了就是根据姓名进行groupby,再把记分sum一下,代码如下:

defBlacklist(self):blacklist=self.Vio_file.groupby(违章人员姓名).sum()blacklist=blacklist[blacklist[本次违章扣分]=12]print(blacklist)

结果如下:

基本上是可以的,但是仍然需要对列重命名,而且还需要剔除“违章条款”一列:

blacklist.rename(columns={本次违章扣分:总扣分},inplace=True)self.blacklist=blacklist[总扣分]#注意,我们后边还需要写入excel,需要跨函数调用变量,所以这里一定要加self

运行一下:

这部分也搞定了。

l最后:写入Excel

这部分不展开讲了,大家只需要理解大致思路即可:首先excel是分层次的,首先你打开这个应用,这个应用是个app(即application,指应用程序),app打开后你点完“新建”后,打开的是一个workbook,workbook下包含多个sheet,每个sheet里的每个单元格是cell,整列、整行操作一般都是按照多个连续的cell为对象进行操作的,这块儿我直接上代码了,如果有兴趣自己可以百度一下模块的用法:

defFile_write_in(self):app=xw.App(visible=True,add_book=False)#打开excel程序workbook=app.books.open(r最终表格.xlsx)#打开workbookworkbook.sheets[01区域违章分析].range(A1).value=self.dep_analyse#在workbook的“01区域违章分析”sheet里的“A1”格子里按顺序插入self.dep_analyse的值,因为dep_analyse变量我们是跨函数调用,所以在前边的函数中已经加入了“self.”前缀workbook.sheets[02分包商违章分析].range(A1).value=self.contractor_databaseworkbook.sheets[03吊销场内运输司机名单].range(A1).value=self.blacklistworkbook.sheets[01区域违章分析].autofit()#宽高自适应workbook.sheets[02分包商违章分析].autofit()workbook.sheets[03吊销场内运输司机名单].autofit()workbook.save(r最终表格.xlsx)#保存文件workbook.close()#关闭workbookapp.quit()#关闭excel程序

查看一下最终结果:

好的,这下就搞定了。当然各位可能会说表格还是很丑,事实上xlwigns是可以利用api参数调整单元格格式的,但是这块知识相对比较复杂,而且可调节的参数太多,所有在这里就不再讲解了,有兴趣的可以自行百度。

感悟

对于绝大多数工作*而言,Excel绝对是我们日常数据汇总、处理和分析的主要战场,其中周期性的重复工作又占其中绝大多数,对于此类工作,借助Python去帮助处理绝对是上上之策。

虽然对于大部分新手来说,针对实际工作需求去编写一段代码可能会花费大量的时间,但是一旦代码完成,将会持续不断得带来时间上的收益。此外,我们普通员工自身随着年龄的增长,工作效率会逐渐下降,这的确是个残酷的显示问题。但是一旦我们掌握一门计算机语言,效率就会大大提高,从而凸显我们的个人职场竞争力,Python相对于其他语言来说比较容易入门且和我的工作需求比较契合,所以我选择了它。

掌握了编程语言后,我们眼中的数据将会变得不同,对于数据之中所蕴含规律的感知将更加敏锐,对复杂任务的完成思路也会更加清晰。与此同时,Python的学习带给我的不仅仅局限于代码,我更加懂得了如何将一个复杂的任务逐步拆解,变为一个个容易完成的任务。慢慢地,我有了更加清晰的逻辑线条,更加缜密的思维模式,让我在完成冗杂的任务时也能够冷静分析并选择最优解来化解难题,这是在学习编程的过程中我领悟到的,与君共勉。

那么,本期的案例已经临近尾声了,可能有些读者正在犹豫要不要开始学习Python,有些读者正在经历瓶颈期觉得进退两难,但是相信我,你选择了这门语言并且选择了坚持,时间会给你以最好的回馈和答案。当你努力过、付出过,有一天你突然回头,会惊觉自己改变了这么多,甚至超出了原本的预期。那个时候你再回首自己当初所遇到的困难和犹豫,你一定会感谢当初坚持下去的自己。

如果您也想学习编程语言,欢迎私信咨询我们

1
查看完整版本: 学生分享巧用Python管理企业