数据分析在企业日常经营分析中
有三大作用,即现状分析、原因分析、预测分析。
1.2.1 现状分析
现状分析可以告诉你业务在过去发生了什么,具体体现在两个方
面。
第一,告诉你现阶段的整体运营情况,通过各个关键指标的表现情
况来衡量企业的运营状况,掌握企业目前的发展趋势。
第二,告诉你企业各项业务的构成,通常公司的业务并不是单一
的,而是由很多分支业务构成的,通过现状分析可以让你了解企业各项
分支业务的发展及变动情况,对企业运营状况有更深入的了解。
现状分析一般通过日常报表来实现,如日报、周报、月报等形式。
例如,电商网站日报中的现状分析会包括订单数、新增用户数、活
跃率、留存率等指标同比、环比上涨/下跌了多少。如果将公司的业务
划分为华北、东北、华中、华东、华南、西南、西北几个片区,那么通
过现状分析,你可以很清楚地知道哪些区域做得比较好,哪些区域做得
比较差。
1.2.2 原因分析
原因分析可以告诉你某一现状为什么会存在。
经过现状分析,我们对企业的运营情况有了基本了解,知道哪些指
标呈上升趋势,哪些指标呈下降趋势,或者是哪些业务做得好,哪些做
得不好。但是我们还不知道那些做得好的业务为什么会做得好,做得差
的业务的原因又是什么?找原因的过程就是原因分析。
原因分析一般通过专题分析来完成,根据企业运营情况选择针对某
一现状进行原因分析。
例如,在某一天的电商网站日报中,某件商品销量突然大增,那么
就需要针对这件销量突然增加的商品做专题分析,看看是什么原因促成
了商品销量大增。
1.2.3 预测分析
预测分析会告诉你未来可能发生什么。
在了解企业经营状况以后,有时还需要对企业未来发展趋势做出预
测,为制订企业经营目标及策略提供有效的参考与决策依据,以保证企
业的可持续健康发展。
预测分析一般是通过专题分析来完成的,通常在制订企业季度、年
度计划时进行。
例如,通过上述的原因分析,我们就可以有针对性地实施一些策
略。比如通过原因分析,我们得知在台风来临之际面包的销量会大增,
那么我们在下次台风来临之前就应该多准备一些面包,同时为了获得更
多的销量做一系列准备。
浮点数设置:
.2f表示以浮点型展示,且显示小数点后两位,也可以是.3f或者其
他。
>>>print('中国目前男光棍有{:.2f}人,强奸案高发!'.format(11111111))
out:
中国目前男光棍有11111111.00人,强奸案高发!
百分数设置:
>>>print('中国目前男光棍有{:.2%}人,强奸案高发!'.format(98))
out:
中国目前男光棍有9800.00%人,强奸案高发!
利用len()函数来获取字符串长度。
字符串查找:
>>>'测试' in '委托测试'
Out[9]: True
除了in和not in,还可以用find,当用find查找某一字符是否存在于
某个字符串中时,如果存在则返回该字符的具体位置,如果不存在则返
回-1。
>>>'委托测试'.find('测试')
Out[10]: 2
>>>'委托测试'.find('sb')
Out[11]: -1
字符串索引:
是指通过字符串中值所处的位置对值进行选取。需要注
意的是字符串中的位置是从0开始的。
'abcde'[4]
Out[12]: 'e'
'abcde'[1:3]
Out[13]: 'bc'
'abcde'[:3]
Out[14]: 'abc'
'abcde'[3:]
Out[15]: 'de'
获取字符串中最后一位的值
'abcde'[-1]
Out[16]: 'e'
字符串分隔:
是先将一个字符用某个分隔符号分开,然后将分隔后的
值以列表的形式返回,用到的是split()函数。
'a+b+c+d'.split('+')
Out[17]: ['a', 'b', 'c', 'd']
移除字符:
用到的方法是 strip()函数,该函数用来移除字符串首尾的
指定字符,默认移除字符串首尾的空格或换行符.
' a+ b+c +d'.strip()
Out[28]: 'a+ b+c +d'
'absdada'.strip('a')
Out[29]: 'bsdad'
列表的复制:
和字符串的复制类似,也是利用*操作符。
[1,2,4]*3
Out[30]: [1, 2, 4, 1, 2, 4, 1, 2, 4]
列表的合并:
alst=[1,2]
blst=[3,4]
alst+blst
Out[33]: [1, 2, 3, 4]
alst.extend(blst)
alst
Out[44]: [1, 2, 3, 4]
列表中插入新元素:
对列表进行插入数据元素的操作主要有append()和insert()两个函
数可用。这两个函数都会直接改变原列表,不会直接输出结果,需要调
用原列表的列表名来获取插入新元素以后的列表。
函数append()是在列表末尾插入新的数据元素。
alst=[1,2]
alst.append(8)
alst
Out[47]: [1, 2, 8]
函数insert()是在列表的指定位置插入新的数据元素。
alst=[1,2]
alst.insert(1,8)
alst
Out[51]: [1, 8, 2]
获取列表中值出现的次数:
利用count()函数获取某个值在列表中出现的次数。
alst=list('abcdabce')
alst.count('a')
Out[57]: 2
获取列表中值出现的位置:
alst=list('abcabc')
alst.index('c')
Out[65]: 2
获取列表中指定位置的值:
alst=list('abcabc')
alst[:3]
Out[76]: ['a', 'b', 'c']
alst[4:]
Out[77]: ['b', 'c']
alst[1:4]
Out[78]: ['b', 'c', 'a']
alst[-1]
Out[79]: 'c'
删除列表中的值:
alst=list('abcabc')
alst.remove('a')
alst
Out[88]: ['b', 'c', 'a', 'b', 'c']
while alst.count('b')>0:
alst.remove('b')
alst
Out[90]: ['c', 'a', 'c']
对列表中的值进行排序:
对列表中的值排序利用的是sort()函数,sort()函数默认采用升序排
列。
新建一个字典:
先创建一个空的字典,然后向该字典内输入值。
adict={}
adict['a']=10
adict['b']=100
adict
Out[96]: {'a': 10, 'b': 100}
将值直接以键值对的形式传入字典中。
bdict={'c':3,'d':2}
bdict
Out[98]: {'c': 3, 'd': 2}
将键值以列表的形式存放在元组中,然后用dict进行转换。
cdict=dict((['e',9],['f',78]))
cdict
Out[100]: {'e': 9, 'f': 78}
获取字典所有的键、值、键值对:
adict={'a': 10, 'b': 100}
adict
Out[107]: {'a': 10, 'b': 100}
#获取所有的键
adict.keys()
Out[108]: dict_keys(['a', 'b'])
#获取所有的值
adict.values()
Out[109]: dict_values([10, 100])
#获取所有的键值对
adict.items()
Out[110]: dict_items([('a', 10), ('b', 100)])
for key,value in adict.items():
print(key,' ',value)
out:
a 10
b 100
元组与列表相互转换:
a_tup=(3,4,5)
a_tup
Out[123]: (3, 4, 5)
a_lst=[3,4,6]
a_lst
Out[125]: [3, 4, 6]
a_lst=tuple(a_lst)
a_lst
Out[127]: (3, 4, 6)
a_tup=list(a_tup)
a_tup
Out[129]: [3, 4, 5]
zip()函数:
zip()函数用于将可迭代的对象(列表、元组)作为参数,将对象中
对应的元素打包成一个个元组,然后返回由这些元组组成的列表。zip()
函数常与 for 循环一起搭配使用。
alst=list('abcd')
blst=list(range(4))
clst=list(range(8,12))
for x,y,z in zip(alst,blst,clst):
print(x,' ',y,' ',z)
out:
a 0 8
b 1 9
c 2 10
d 3 11
map函数:
map 函数的表现形式是 map(function,agrs),表示对序列 args 中的每
个值进行function操作,最终得到一个结果序列。
a=map(lambda x,y:x+y,[8,3,2],[9,1,7])
list(a)
Out[146]: [17, 4, 9]
模块:
模块是升级版的函数,我们前面说过,在一段程序中可以通过函数
名多次调用函数,但是必须在定义函数的这段程序里面调用,如果换到
其他程序里该函数就不起作用了。
模块之所以是升级版的函数,是因为在任意程序中都可以通过模块
名去调用该模块对应的程序。
Python 中实现多对一的替换:
在 Python 中实现多对一的替换比较简单,同样也是利用 replace()方
法, replace([A,B],C)表示将A、B替换成C。
import pandas as pd
df=pd.DataFrame({'a':range(2,11),'b':list('abdjdadaf')})
df
Out[149]:
a b
0 2 a
1 3 b
2 4 d
3 5 j
4 6 d
5 7 a
6 8 d
7 9 a
8 10 f
df.replace(['a','b'],'c')
Out[150]:
a b
0 2 c
1 3 c
2 4 d
3 5 j
4 6 d
5 7 c
6 8 d
7 9 c
8 10 f
Python 中实现多对多的替换:
在Python中若想实现多对多的替换,同样是借助replace()方法,将
替换值与待替换值用字典的形式表示,replace({"A":"a","B":"b"}表示用a
替换A,用b替换B。
python删除列:
在Python中,要删除某列,用到的是drop()方法,即在drop方法后的
括号中指明要删除的列名或者列的位置,即第几列。
在drop方法后的括号中直接传入待删除列的列名,需要加一个参数
axis,并让其参数值等于1,表示删除列。
df.drop(columns=['销售id','成交时间'])
df.drop(df.columns[[4,5]],axis=1)
python删除行:
df.drop(['0a','1b'],axis=0)
df.drop(index=['0a','1b'])
df.drop(df.index[[0,1,4]],axis=0)
python中查找某个值:
在Python中查看数据表中是否包含某个值用到的是isin()方法,而且
可以同时查找多个值,只需要在isin方法后的括号中指明即可。
可以将某列数据取出来,然后在这一列上调用 isin()方法,看这一
列中是否包含某个/些值,如果包含则返回True,否则返回False。
df['年龄'].isin([31,47])
DataFrame插入新列:
df.insert(2,'商品类别',['a','b','c'])
df['商品类别']=['a','b','c']
DataFrame行列互换:
df.T
apply()与applymap()函数:
apply()函数主要用于对DataFrame中的某一column或row中的元素执
行相同的函数操作.
df['c1'].apply(lambda x:x+1)
applymap()函数用于对DataFrame中的每一个元素执行相同的函数操
作。
df.applymap(lambda x:x+1)
python相关性运算:
df['col1'].corr(df['col2']) #求两列的相关系数
df.corr() #求取整个DataFrame表中各字段两两之间的相关性。
#返回星期几
import datetime
datetime.datetime.now().weekday()+1
Python中周几是从0开始数的,周日返回的是6,所以在后面加1。
#返回一年里的第几周
import datetime
datetime.datetime.now().isocalendar()[1]
#只展示日期
import datetime
datetime.datetime.now().date()
Out[12]: datetime.date(2019, 9, 4)
#只展示时间
import datetime
datetime.datetime.now().time()
Out[15]: datetime.time(6, 45, 24, 682978)
#strftime()函数自定义时间和日期的格式:
datetime.datetime.now().strftime('%y-%m-%d')
Out[23]: '19-09-04'
datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S')
Out[24]: '2019-09-04 06-49-38'
#将字符串格式的时间转换为时间格式:
str_time='2018-10-14'
type(str_time)
Out[31]: str
from dateutil.parser import parse
parse(str_time)
Out[33]: datetime.datetime(2018, 10, 14, 0, 0)
#选取成交时间在2018年8月9日之后的订单
df[df.成交时间>datetime(2018,8,9)]
两个时间之差:
在Excel中两日 期直接做差会得到一个带小数点的天数, 如果只 想
看两日 期之间差多少天, 那么 直接取整数部分即可; 如果想看两日 期之
间差多少小时、 分钟, 则需要对小数部分进行计算, 小数部分乘24得到
的结果中的整数部分就是小时数, 它的小数部分再乘60就是分钟数。
在Python中两个时间做差会返回一个timedelta对象, 该对象中包含
天数、 秒、 微秒三个等级, 如果要获取小时、 分钟, 则需要进行换算。
cha=datetime.datetime(2018,5,21,19,50)-datetime.datetime(2018,5,18,20,32)
cha
Out[46]: datetime.timedelta(days=2, seconds=83880)
cha.days#返回天的时间差
Out[47]: 2
cha.seconds#返回秒的时间差
Out[48]: 83880
cha.seconds/3600 #换算成小时的时间差
Out[49]: 23.3
时间偏移:
时间偏移是指给时间往前推或往后推一段时间, 即加或减一段时
间。
Excel实现
由于Excel中的运算单位都是天, 因此若想对某一个时间具体加/减
某一单位的时间, 如果是加/减小时或者分钟, 则需要把小时或分钟换
算成对应的天。
Python实现
在Python中实现时间偏移的方式有两种: 第一种是借助timedelta,
但是它只 能偏移天、 秒、 微秒单位的时间; 第二种是用Pandas中的日 期
偏移量( date offset) 。
● timedelta
由于timedelta只 支持天、 秒、 微秒单位的时间运算, 如果是其他单
位的时间运算, 则需要换算成以上三种单位中的一种方可进行偏移。
● date offset
date offset 可以直接实现天、 小时、 分钟单位的时间偏移, 不需要
换算, 相比timedelta要方便一些。
from pandas.tseries.offsets import Day,Hour,Minute
date=datetime.datetime(2018,5,19,20,32)
date+Day(1)#往后推1天
Out[67]: Timestamp('2018-05-20 20:32:00')
date+Hour(1)#往后推1小时
Out[68]: Timestamp('2018-05-19 21:32:00')
date+Minute(1)#往后推1分钟
Out[69]: Timestamp('2018-05-19 20:33:00')
date-Minute(1)#往前推1分钟
Out[70]: Timestamp('2018-05-19 20:31:00')
神奇的aggregate方法:
前面用到的聚合函数都是直接在DataFrameGroupBy上调用的, 这样
分组以后所有列做的都是同一种汇总运算, 且一次只 能使用一种汇总方
式。
aggregate的第一个神奇之处在于, 一次可以使用多种汇总方式, 比
如下面的例子先对分组后的所有列做计数汇总运算, 然后对所有列做求
和汇总运算。
df.groupby('客户分类').aggregate(['count','sum'])
aggregate的第二个神奇之处在于, 可以针对不同的列做不同的汇总
运算, 比如下面的例子, 我们想看不同类别的用户 有多少, 那么 对用户
ID 进行计数; 我们想看不同类别的用户 在7、 8月 的销量, 则需要对销
量进行求和。
df.groupby('客户分类').aggregate({'用户id':'count','7月销量':'sum'})
对分组后的结果重置索引:
df.groupby('客户分类').sum().reset_index()
表的横向拼接:
表的横向拼接就是在横向将两个表依据公共列拼接在一起。
在Excel中实现横向拼接利用的是vlookup()函数, 关于vlookup()函数
这里就不展开了 , 相信大家应该都很熟悉。
在 Python 中实现横向拼接利用的 merge()方法, 接下来的几节主要
围绕 merge()方法展开。
pd.merge()连接键可以有多个:
公共列可以有多列, 也就是连接键可以有多个, 比如下面这个例子
用学号和姓名 两列做连接键:
pd.merge(df1,df2,on=['姓名','学号'])
表的纵向联结:
在Python中想纵向合并两个表, 需要用到concat()方法。
注意纵向合并后可以有重复值。
pd.concat([df1,df2],ignore_index=True).drop_duplicates()
导出excel文件时去掉无意义的默认自然数索引:
上面导出文件中关于索引 的参数都是默认的, 也就是没有对索引 做
什么 限制, 但是我们可以看到index索引 使用的是从0开始的默认自 然数
索引 , 这种索引 是没有意义的, 设置参数index=False就可以在导出时把
这种索引 去掉, 具体实现如下所示。
df.to_excel(r'd:\users\lele\desktop\测试.xlsx',sheet_name='测试文档',index=False)
导出时设置要导出的列:
有的时候一个表的列数很多, 我们并不需要把所有的列都导出, 这
个时候就可以通过设置columns参数来指定要导出的列.
导出 为.csv文件:
在Excel中要将文件保存为.csv格式, 直接将文件另存为, 在另存为
时有两种.csv文件可选, 这两种文件虽然后缀均为.csv, 但是编码方式不
同, CSV UTF-8(逗号分隔)(*.csv)采用的编码格式是 UTF-8, 而 CSV(逗
号分隔)(*.csv)采用的编码格式是 gbk编码。
分隔符号就是用来指明导出文件中的字符之间是用什么 来分隔的,
默认使用逗号分隔, 常用的分隔符号还有空格、 制表符、 分号等。 用参
数sep来指明要用的分隔符号。
设置编码格式:
在Python 3中, 导出为.csv文件时, 默认编码为UTF-8, 如果使用默
认的UTF-8编码格式, 导出的文件在本地电脑打开以后中文会乱码, 所
以一般使用utf-8-sig或者gbk编码。
将文件导出到多个Sheet:
有的时候一个脚本一次会生成多个文件, 可以将多个文件分别导出
成多个文件, 也可以将多个文件放在一个文件的不同 Sheet 中, 这个时
候要用 ExcelWriter()函数将多个文件分别导出到不同Sheet中, 具体方法
如下:
#声明一个读写对象,excelpath为文件要存放的路径
writer=pd.ExcelWriter(excelpath,engine='xlsxwriter')
#分别将表df1、df2、df3写入Excel中的sheet1、sheet2、sheet3并命名为表1、表2、表3.
df1.to_excel(writer,sheet_name='表1')
df2.to_excel(writer,sheet_name='表2')
df3.to_excel(writer,sheet_name='表3')
#保存读写的内容
writer.save()
用 plt.subplots函数建立坐标系:
plt.subplots函数也是plt库的一个函数, 它与subplot2grid函数和
subplot函数的不同之处是, subplot2grid函数和subplot函数每次只 返回一
个坐标系, 而subplots函数一次可以返回多个坐标系。
fig,axes=plt.subplots(2,2)#将图表的整个区域分成2行2列,并将4个坐标系全部返回。
你想在哪个坐标系里面绘图通过axes[x,y]指明即可。 现在我们在上
例的图表中绘图, 首先在[0,0]坐标系中绘制折线图, 然后在[1,1]坐标系
中绘制折线图, 具体实现如下所示。
import numpy as np
x=np.arange(6)
y=np.arange(6)
axes[0,0].plot(x,y) #在[0,0]坐标系中绘制折线图
axes[1,1].bar(x,y) #在[1,1]坐标第中绘制柱状图
几种创建坐标系方法的区别:
第一种创建坐标系的方法 add_subplot 属于对象式编程, 所有的操
作都是针对某个对象进行的, 比如先建立一块画布, 然后在这块画布上
建立坐标系, 进而在坐标系上绘图。 而后三种建立坐标系的方法属于函
数式编程, 都是直接调用 plt 库里面的某个函数或者方法达到创建坐标
系的目 的。
对象式编程的代码比较烦琐, 但是便于理解; 函数式编程虽然代码
简洁, 但是不利于新人掌握整体的绘图原理, 所以建议大家刚开始的时
候多使用对象式编程, 当大家对整个绘图原理很熟悉时, 再尝试使用函
数式编程。
这两种编程方式不仅体现在创建坐标系中, 在接下来的一些操作中
也会有涉及, 有的时候两者会交叉使用, 也就是在一段代码中既有函数
式编程, 也有对象式编程。
NumPy数组的类型转换:
我们在前面说过, 不同类型的数值可以做的运算是不一样的, 所以
要把我们拿到的数据转换成我们想要的数据类型。 在 NumPy 数组中转
换数据类型用到的方法是astype(), 在astype后的括号中指明要转换成的
目 标类型即可。 例子如下所示。
arr_float=arr.astype(np.float64)#将arr数组从int类型转换为float类型
arr_str=arr.astype(np.string_) #将arr数组从int类型转换为str类型