本周学习主要内容为Pandas剩余部分(自定义函数运算,分组聚合进阶,可视化,数据规整)、重塑和轴向旋转、透视表和交叉表、离散化
软件开发流程:
数据分析流程:
不断迭代
拓展流程
优化迭代
业务性数据分析师
综合:数据分析报告
实现数据分析指标计算的常用操作:
交叉表 -> 透视表 -> 分组聚合旋转 -> 自定义函数 (狭窄到广泛的顺序)
越往底层书写越难,应用范围越广。越往上层书写越简单,应用范围越窄
是各种电子表格程序和数据分析软件中一种高级数据汇总表格形式
数据源表通常只包含行和列,经常有重复和无用之出现在各列下,因而导致源表不能传递有价值的信息。这是可以用[透视]方法调整元彪的布局用作更清晰的展示。
透视表是用来汇总其他表的数剧:
这种动态将源表转换得到想要终表的旋转过程(pivoting),叫做透视表
透视表默认聚合函数为mean平均值
如果想使用非默认mean的其他的聚合函数,传给aggfun即可(传入函数名称或函数字符串)
如果使用count或者len可得到有关分组大小的交叉表(计数或频率)
传入值类型,一般为函数名字符串,函数名,numpy函数名:
衡量能否做数据分析项目的基准:
乞丐版交叉表(1列数据的频度情况,只有一个维度,分组聚合实现)
#表格某一列所有内容的出现次数
t2.groupby(‘day’).size().sort_values(ascending=False)
t2.day.value_counts() #同上
常用的crosstab交叉表函数结构(2列数据的频度情况)
#常见参数:行索引,列索引,分项小计
pd.crosstab(tips.time,[tips.smoker,tips.day],margins=True)
常用的Pivot_table透视表函数结构
#常见参数:需要计算的列,行索引,列索引,分项小计(默认False),自定义计算函数(默认mean),缺失值填充
tips.pivot_table([‘tip_pct’,‘size’],index=[‘time’,‘day’],columns=‘smoker’,margins=True,aggfunc=len,fill_value=0)
#交叉表只要把aggfun参数值改为len即可
底层:使用分组聚合和轴向旋转实现透视表
#分组:行索引,列索引;郡治局和,行索引转为列索引;填充缺失值为0
tips.groupby([‘time’,‘day’,‘smoker’)[‘size’,‘tip_pct’].mean().unstack().fillna(0)
#交叉表只要把聚合函数由.mean()改为.size()即可
交叉表(cross-tabulation,简称crosstab)是一种用于计算分组频率的特殊透视表
- 透视表由分组后聚合函数为平均值的表旋转而成
- 交叉表就是聚合函数为个数的透视表
有许多用于重新排列表格型数据的基础运算。这些函数也称作重塑(reshape)或轴向旋转(pivot)运算
数据重塑和轴向旋转操作:表示转换一个表格或向量的结构,使其适合于进一步分析
层次化索引为DataFrame数据的重排任务提供了一种具有良好一致性的方式。主要功能有:
二者互为逆运算
注意:
- Series没有stack属性(因为Series没有列)
- 对DataFrame进行unstack操作时,作为旋转轴的级别将会成为结果中的最低级别
对层次化索引的Series,可以用unstack将其重排为一个DataFrame
unstack默认操作的是最里层,stack也是,传入分层级别编号或name即可对其它级别进行unstack操作
data.unstack().unstack() #两次unstack转置完成,行列索引交换位置
data.T #转置快捷操作 同上
-------------------------------------
state Ohio Colorado
number
one 0 3
two 1 4
three 2 5
用分组聚合(groupby)和重塑(unstack)一般可以实现所有的数据重塑功能
表格长宽转换也是一种透视表操作
二者互为逆操作
将一列拆分为多列
多个时间序列数据通常是以所谓的“长格式”(long)或者“堆叠格式”(stacked)存储在数据库和CSV中的
数据规整的一般分类:
本质上,groupby传入的数据并不是行索引或列索引,而是任意一个和数据结构对应的序列(布尔值序列、列表、数组、字典、Series)
#按行分组
df.groupby('name').sum() #简写
df.groupby('name',axis=0).sum() #完整
#按行分组,自定义布尔数组做分组基准
ddd = [True,True,False,False,False,False,True]
df.groupby(ddd,axis=0).sum()
df.groupby(df.dtypes,axis=1).sum()
#手动将分组基准传入,结果同上
fff = ['object','int64','int64','int64','object']
df.groupby(fff,axis=1).sum()
#假设一直列的分组关系,并希望根据分组计算列的和
mapping = {
'a':'red','bc':'red','c':'blue','d':'blue','e':'red','f':'orange'}
# 多写或少写不会执行,多了一个f,不会影响分组
people.groupby(mapping,axis=1).sum()
people.groupby(len,axis=1).sum()
在分组聚合的split-apply-combine过程中,apply是核心,Python本身有高阶函数apply()来实现
自定义聚合方式:aggregate(),或agg()
之前的聚合方式,所有列只能应用一个相同的聚合函数
agg()自定义聚合方式的优势:
聚合参数是列表
聚合参数就是字典
聚合参数是自定义函数
自定义聚合方式可以:
每个列应用不同的聚合方式
一个列应用多个聚合方式
Pandas可视化是基于Matplotlib的上层封装
正常工作一般先用Pandas可视化,再辅以Matplotlib修改组件
Pandas可视化的优势:
Pandas可视化的劣势:
和密度估计图比直方图的优势:
Python数据科学的基本方式是:向量化运算(矢量化运算),并行运算
如果需要对Pandas数据进行操作或运算(按运算速度排名:)
针对Series的map函数,会将自定义函数应用到Series对象的每个值
# 标量运算:for循环遍历实现
a2 = 0
for i in a:
a2 = a2 + i
a2
sum(a) # 底层实现也是循环遍历
-------------------------
# 向量运算,自带函数
a.sum()
np.sum(a.values)
#标量运算
a2 = []
for i in a:
a2.append(i + 1 - 2 * 3 / 4)
a2
--------------------------
#向量运算
a + 1 - 2 * 3 / 4
#自定义函数
def aaa(x):
return x + 1 - 2 * 3 / 4
a.map(aaa) #Sereis使用map进行自定义函数运算
a.apply(aaa) #Series也能使用apply
-----------------------------
a.apply(lambda x:x + 1 - 2 * 3 / 4) #lambda表达式,乞丐版函数(匿名函数)
DataFrame的apply自定义函数应用,复杂,重要
Pandas的统计运算方法,和Numpy基本一致
默认针对0轴(行)做运算,大部分函数可加参数axis=1 改为对列运算
函数 解释
- .describe():针对0轴的统计汇总,计数/平均值/标准差/最小值/四分位数/最大值
- .sum():计算数据的综合,按0轴计算(各行计算),下同,要按列计算参数1
- .count():非NaN值数量
- .mean() .median() .mode():计算数据的算术平均值/中位数/众数
- .var() .std():计算数据的方差/标准差
- .min() .max():计算数据的最小值/最大值
- .idxmin() .idxmax():计算数据第一最大值/最小值所在的位置的索引,给索引或切片使用(自定义索引,排除null/NA等空值)
b
时间单位:
结论:
如果在两个数据之间可以插入新的数据,数据的应用不会出错,就是连续数据,否则就是离散数据
数据去重后的数量,剩下的唯一值和源数据的数量比值是多少(即唯一值相对总之数量多不多)
一般性的:如果唯一值太多,就是连续数据,反之是离散数据(多的定义不固定,一般超过30种就算多,可以用直方图理解)
特殊的:如果原数据本来就少,看比例,唯一值占比高依然是连续数据
总之:如果去重后的数据总量多且占比高,就可以认为是连续数据,反之是离散数据
为何区分:
不同数据做指标运算的时候是不一样的
连续数据:可以运算
离散数据:不可以运算,但可以做计数
数据分析时,为了方便分析,有时需要将连续数据转为离散数据(离散化,面元划分)
(离散数据转连续数据需求较少,因为计算出的指标毫无意义,例如性别计算出平均值0.5,但也有这种情况)
为了便于分析,连续数据常常被离散化或拆分为“面元”,bin(分组区间)
连续数据离散化:连续数据要分析智能化直方图,无法分组聚合,所以可以将这些数据离散化,之后进行分组聚合计算
一个codes属性中的年龄数据标签
一个表示不同分类的类型数据
cut是保持区间间隔相同的,每个区间内值个数不同
qcut是保持每个区间内值个数一直,区间间隔不相同
为了分析方便,一般把连续数据转为离散数据,便于其作为分组基准
有时也需要将离散值转为连续值(可理解为将字符串转为数值),如供机器学习算法
一种常用与统计建模或机器学习的转换方式是:将分类变量(categorical variable)转换为哑变量、指标矩阵(虚拟变量,duress(one-hot)编码变量)
如果DataFrame的某一列含有k个不同值,则可以派生出一个k列矩阵或DataFrame(其值全为1和0)
pandas有一个get_dummies函数可以实现该功能
将不能计算的字符串转为可以计算的数值(表格,或矩阵)
字符串:‘一个对统计应用有用的方法:结合get_dummies和如cut之类的离散化函数’
[统计,应用,有用,方法,结合,离散化,函数]
将人能识别的字符串,转为计算机能计算的值
对单列的连续数据进行指标计算:
对单列的连续数据进行可视化:
#条形图
a.gender.value_counts().plot.bar(
width = 0.5, #柱子粗细
color='r',
alpha = 0.3
)
plt.show()
#饼图
a.gender.value_counts().plot.pie(
figsize=(8,8), #图像大小
explode=(0,0.1), #突出块,突出比例
autopct='%1.1f%%', #显示百分比方式
startangle=90 #饼图起始角度,读属,默认0为右侧水平180度开始,逆时针旋转
)
plt.show()
出指标时同样参照上面的顺序实现
修改Series和DataFrame索引的几种方式:
直接赋值修改索引:
替换索引值:rename()
重建整个索引:reindex(),创建一个适应新索引的新对象
普通列和索引列互相交换:set_index(), reset_index()
.sort_index()在指定轴上根据索引进行排序,索引排序后内容会跟随排序
利用numpy.random.permutation函数可以实现对Series或DataFrame的列的随机排序工作(permuting,随机重排序)
通过需要排列的轴的长度调用permutation,可产生一个表示新顺序的整数数组:
choice(),从一个序列中随机抽取某些值
#按行索引采样
df.index
index = np.random.choice(df.index,size=3,replace=False)
df.loc[index]
------------------
#按行按列随机采样
df.index
df.columns
index = np.random.choice(df.index,size=3,replace=False)
columns = np.random.choice(df.columns,size=2,replace=False)
df.loc[index,columns]
对指定数据(如缺失数据、重复数据)进行处理(检查、替换、删除)
#重复行查询:
#布尔型Series,各列重复值交集
data.duplicated()
-------------------
#重复行移除
data[-data.duplicated()]
data.drop_duplicates()
-------------------
#移除自定义重复行
data.drop_duplicates('k1')
移除重复索引值
检测和过滤异常值
Pandas中,不论缺失值是None还是np.nan,都会被转化为NaN形式
NaN:非数字,not a number,Pandas中他表示缺失或NA值,便于被检测出来本质上就是np.nan
Pandas的对象可以跳过缺失值进行运算4
适用于单列判断哪些行是缺失值
DataFrame不能通过布尔查询方式过滤缺失值,必须使用Pandas的特定方法过滤
查到缺失值后,Series可以直接过滤,DataFrame需要进一步处理(填充或删除)
Pandas提供了大量方法,能轻松对Series,DataFrame进行合并操作
两个表必须有相关性,才有合并的需要
以两个表相关的列或行索引为基准合并
方法1:使用查询和添加列进行表合并
(比较麻烦,且行列如不对应容易出现问题)
df3 = pd.merge(df1,df2)
------------------------
name group date
0 张三 DBA 2012
1 李四 PM 2004
2 王五 PM 2014
3 赵六 HR 2008
pd.merge(df3,df4)
------------------------
name group date leader
0 张三 DBA 2012 钱大
1 李四 PM 2004 孙二
2 王五 PM 2014 孙二
3 赵六 HR 2008 周三
#方法1:join
df1a.join(df2a)
df1a.join(df2a).reset_index()
#方法2:merge
pd.merge(df1a,df2a,left_index=True,right_index=True) #merge实现,同上
#方法3:表格查询和修改
df2a1 = df2a.copy()
df2a1['group'] = df1a['group']
df2a1.reset_index()
参数how
参数on指定用于合并的主键
合并后的数据集中,之前相同的列名会被默认加上_x等后缀用于区分
参数suffixes可以自定义后缀
有一类数据组合问题不能用简单的合并(merge)或链接(concatenation/即concat)运算来处理。如合并全部或部分重叠的两个数据集
距离:使用Numpy的where函数,就表示一种等价于面向数组的if-else
以a为基准合并,a的缺失值使用b填充
方法1:使用原生方式打补丁(a2的缺失值使用b2填充)
#1:使用b2填充a2的缺失值(打补丁)
a2[a2.isnull()] = b2
#2:合并数据
a22 = a2.append(b2)
#3:去重排序
a22.index.duplicated()
a22[~(a22.index.duplicated())].sort_index()
方法2:使用combine_first方法,先打补丁再合并,在去重排序
a2 = a[2:].copy()
b2 = b[2:].copy()
a2.combine_first(b2)