一、学习知识点摘要
1、数据总体了解
2、缺失值和唯一值
3、深入数据-查看数据类型
4、数据间的相关关系
5、用pandas_profiling生成数据报告
二、学习内容
(一)、数据总体了解
1、读取数据集并了解数据集的大小,原始特征维度
• 导入数据分析及可视化过程需要的库(具体需要哪几个库详见task1学习笔记),导入方法 ' import 库 as xx '
import pandas as pd
import numpy as np
...
import datetime
import warnings
warnings.filterwarnings('ignore')
• 读取文件
data_train = pd.read_csv(('train.csv')
data_test_a = pd.read_csv('textA.csv')
注:1、pandas读取数据时相对路径载入报错时,尝试使用os.getcwd()查看当前工作目录。
2、CSV是用半角逗号(',')作为字段值的分隔符;DSV是用制表符(Tab,'\t'垂直制表符)作为字段值的分隔符。Python的csv模块准确来讲应该叫dsv模块(delimiter-separated values)。delimiter的默认值是半角逗号,当改为'\t'时,被处理的文件就是TSV。
3、读取较大的文件时可以通过nrows参数来设置读取的行数从而实现分块读取(具体操作与读取函数具体值时使用的head()函数类似)。
data_train_sample = pd.read_csv("train.csv",nrows=5)
4、chunksize参数
当数据集比较大时,如果使用read_csv()的方法去读取这个文件,必然会占用很多内存,导致服务器崩盘。这时候就可以利用chunksize实现分区处理。设定chunksize参数的值使得每次读取只消耗相应行数对应的内存,从而可以有效解决消耗内存过多的问题。
i = 0
chunker = pd.read_csv("train.csv",chunksize=5)
for item in chunker:
print(type(item))
print(len(item))
i+=1
if i >= 4:
break
• 查看数据集的样本个数和原始特征维度
' data_train.columns ' 用于获取数据集的具体列名(column)
id | 为贷款清单分配的唯一信用证标识 |
loanAmnt | 贷款金额 |
term | 贷款期限(year) |
interestRate | 贷款利率 |
installment | 分期付款金额 |
grade | 贷款等级 |
subGrade | 贷款等级之子级 |
employmentTitle | 就业职称 |
employmentLength | 就业年限(年) |
homeOwnership | 借款人在登记时提供的房屋所有权状况 |
annualIncome | 年收入 |
verificationStatus | 验证状态 |
issueDate | 贷款发放的月份 |
purpose | 借款人在贷款申请时的贷款用途类别 |
postCode | 借款人在贷款申请中提供的邮政编码的前3位数字 |
regionCode | 地区编码 |
dti | 债务收入比 |
delinquency_2years | 借款人过去2年信用档案中逾期30天以上的违约事件数 |
ficoRangeLow | 借款人在贷款发放时的fico所属的下限范围 |
ficoRangeHigh | 借款人在贷款发放时的fico所属的上限范围 |
openAcc | 借款人信用档案中未结信用额度的数量 |
pubRec | 贬损公共记录的数量 |
pubRecBankruptcies | 公开记录清除的数量 |
revolBai | 信贷周转余额合计 |
revolUtil | 循环额度利用率,或借款人使用的相对于所有可用循环信贷的信贷金额 |
totalAcc | 借款人信用档案中当前的信用额度总数 |
initialListStatus | 贷款的初始列表状态 |
applicationType | 表明贷款是个人申请还是与两个共同借款人的联合申请 |
earliesCreditLine | 借款人最早报告的信用额度开立的月份 |
title | 借款人提供的贷款名称 |
policyCode | 公开可用的策略代码=1新产品不公开可用的策略代码=2 |
n系列匿名特征(n1-n14) | 为一些贷款人行为计数特征的处理 |
2、通过info熟悉数据类型
data_train.info()
3、粗略查看数据集中各特征基本统计量(包括count[数量]、mean[均值]、std[方差]、min、25%、50%、75%、max)
data_train.describe()
(二)、缺失值和唯一值
1、查看数据缺失值情况
• 查看缺失值并统计含有缺失值的列数 ' data_train.insull().any().sum() '
• 查看缺失特征中缺失率大于50%的特征
have_null_fea_dict = (data_train.isnull().sum()/len(data_train)).to_dict()
fea_null_moreThanHalf = {}
for key,value in have_null_fea_dict.items():
if value > 0.5:
fea_null_moreThanHalf[key] = value
• 具体地查看缺失特征及缺失率 (NaN的可视化)
missing = data_train.isnull().sum()/len(data_train)
missing = missing[missing > 0]
missing.sort_values(inplace=True)
missing.plot.bar()
纵向比较:查看某一列NaN存在的个数是否真的很大,如果NaN存在的过多,说明这一列对label的影响几乎不起作用了,可以考虑删掉。如果缺失值很小一般可以选择填充。
横向比较:如果在数据集中,某些样本数据的大部分列都是缺失的且样本足够的情况下可以考虑删除。
2、查看唯一值特征情况
one_value_fea = [col for col in data_train.columns if data_train[col].nunique() <= 1]
(三)、深入数据-查看数据类型
特征一般由类别型特征和数值型特征组成,而数值型特征又分为连续性和离散型。类别型特征分为数值关系和非数值关系(例如成绩中的A、B、C、D是A优于其他(数值型)还是只是单纯的分类(非数值型))
• 数值型特征
数值型特征本是可以直接入模的,但往往风控人员要对其做分箱,转化为WOE编码进而做标准评分卡等操作。从模型效果上来看,特征分箱主要是为了降低变量的复杂性,减少变量噪音对模型的影响,提高自变量和因变量的相关度。从而使模型更加稳定。
numerical_fea = list(data_train.select_dtypes(exclude=['object']).columns)
# select_dtypes() 的作用是筛选数据类型,可以通过控制参数exclude来筛选出具有某种类型的数据
category_fea = list(filter(lambda x:x not in numerical_fea,list(data_train.columns)))
• 过滤数值型类别特征
三 、学习问题与解答
Q1:什么的是EDA?
A1:EDA(Exploratory Data Analysis) ——探索性分析。主要包括:分布分析、统计量分析和相关分析。分布分析:定量定性的分析;统计量分析:集中、离散趋势和分布形状;相关分析:单个图、图矩阵、相关系数。要充分了解和分析数据需要了解外部信息(数据的现实意义)和内部信息(方差、标准差、峰度、偏度等或者是绘图)。
ps:答案来源
Q2:怎么理解代码 :' data_train.head(3).append(data_train.tail(3)) ' ?
A2:data_train.head() :返回data_train的前几行数据,默认为前5行;
data_train.tail():返回data_train的后几行数据,默认为后5行;
append()方法用于在列表末尾添加新的对象。应用在这一行代码里即:在前3行数据形成的列表末尾添加后3行数据形成的列表,从而形成一个新的列表。
ps:答案来源
Q3:怎么理解代码: ' data_train.isnull().any().sum() ' ?
A3:data_train.isnull():元素级别的判断。把对应的元素都列出来,元素为空或者NaN就显示True,否则就为False。(对于样本很大时不推荐)
data_train.isnull().any():列级别的判读。只要该列有为空或者NaN的元素就显示True,否则就为False。运行结果就是判断出哪些列存在缺失值。
data_train.isnull().sum():将列中为空的个数统计出来。
ps:答案来源
Q4:to_dict() 函数是什么含义及用法?
A4:data_train.to_dict(self,orient='dict',into=) 这个函数中只需要填写一个参数:orient ,但对于写入的orient的不同,字典的构造方式也不同。
orient = 'dict' 是函数默认的,转化后的字典形式为:{column(列名):{index(行名):value(值)}}
orient = 'list' 转化后的字典形式为:{column(列名):{[value](值)}}
orient = 'series' 转化后的字典形式为:{column(列名)}:Series(values)(值)}
orient = 'split' 转化后的字典形式为:{'index':[index],'columns':[columns],'data':[values]}
orient = 'records' 转化后的字典形式为:[{column(列名):value(值)...{column:value}]
orient = 'index' 转化后的字典形式为:{index(值):{column(列名):value(值)}}
其中,{}表示字典数据类型,字典中的数据是以{key:value}的形式显示,是键名和键值一一对应形成的。
ps:答案来源
Q5:nunique()函数是什么含义及用法?
A5:nunique()函数是返回某列中唯一值的个数。
顺便辨析一下: unique()函数是返回列中的所有唯一值。
ps:答案来源
Q6:filter()函数是什么含义和用法?
A6:filter(function,iterable):将一个可迭代对象(iterable)中的元素,通过函数(function)进行判断,筛选出需要的元素。
用iterable中函数function返回真的那些元素,构建一个新的迭代器。iterable可以是一个序列,一个支持迭代的容器或一个迭代器。如果function是None,则会假设它是一个身份函数,即iterable中所有返回假的元素都会被移除。
ps:答案来源
Q7:lambda()函数是什么含义和用法?
A7:1、lambda语法
lambda [arg1,arg2,arg3......argn]:expression
[arg...]是参数列表,可以有非常多种形式。
a,b
a=1,b=2
*args
**kwargs
a,b=1,*args
空
......
expression是一个参数表达式。表达式出现的参数需要在[args......]中有定义,并且表达式只能是单行的,只能有一个表达式。
1
None
a + b
sum(a)
1 if a > 10 else 0
......
2、lambda特性
• lambda函数是匿名的
• lambda函数有输入和输出
• lambda函数拥有自己的命名空间
lambda x,y: x*y
lambda:None
lambda *args: sum(args)
lambda **kwargs: 1
3、lambda常见用法
• 将lambda函数赋值给一个变量,通过这个变量间接调用该lambda函数。
add = lambda x,y: x+y
• 将lambda函数赋值给其他函数,从而将其他函数用该lambda函数替换
#为了把标准库time中的函数sleep的功能屏蔽(Mock),我们可以在程序初始化时调用:
time.sleep=lambda x:None
#这样,在后续代码中调用time库的sleep函数将不会执行原有的功能。
#例如:
time.sleep(3) #程序不会休眠3秒钟,而是因为lambda输出为None,所以这里结果是什么都不做
• 将lambda函数作为参数传递给其他函数。(经典用法就是常见的几种高阶函数,学习内容中查看数据类型中的lambda就是这个用法)
4、lambda用法之高阶函数
• map()函数
描述:根据函数对指定序列做映射
语法:map(function,iterable,...)
参数:function是函数;iterable是一个或多个序列
返回值:Python2返回的是列表;Python3返回的是迭代器
#计算平方数
#一般写法
def square(x):
return x ** 2
map(square,[1,2,3,4,5])
#匿名函数写法
map(lambda x:x ** 2,[1,2,3,4,5])
#结果:
[1,4,9,16,25]
#提供两个列表,将其相同索引位置的列表元素进行相加
map(lambda x,y:x + y,[1,3,5,7,9,],[2,4,6,8,10])
#结果:
[3,7,11,15,19]
• reduce()函数
描述:对参数序列函数中的元素进行累积
语法:reduce(function,iterable[,initializer])
参数:function是函数(有两个参数);iterable是可迭代对象;initializer可选,是初始函数
返回值:返回函数计算结果
#两数相加
#一般写法
def add(x,y):
return x + y
reduce(add,[1,3,5,7,9]) #计算列表元素和:1+3+5+7+9
"""
执行步骤解析:
调用reduce(add,[1,3,5,7,9])时,reduce函数将做如下计算:
1、先计算前两个元素:f(1,3),结果为4;
2、再把结果和第3个元素计算:f(4,5),结果为9;
...
"""
#匿名函数写法
reduce(lambda x,y:x + y,[1,2,3,4,5])
#结果:
15
#把序列[1,3,5,7,9] 变换成整数 13579,reduce就可以派上用场:
from functools import reduce
def fn(x,y):
return x * 10 + y
reduce(fn,[1,3,5,7,9])
#结果:
13579
• sorted()函数:
描述:对所有可迭代的对象进行排序操作
★sort和sorted的区别:
sort无返回值,只是内建函数;sorted是返回一个新的list,而不在原来的基础上进行操作
语法:sorted(iterable[,cmp[,key[,reverse]]])
参数:iterable是可迭代对象;cmp是比较函数,有两个参数,此函数遵循大于则返回1,小于则返回-1,等于则返回0;key主要是用来比较的元素,只有一个参数;reverse是排序规则,reverse = True 降序,reverse = False 升序(默认)
返回值:返回重新排序的列表
#一般写法
#简单排序
a = [5,7,6,3,4,1,2]
b = sorted(a)
print(a)
print(b)
#结果:
[5,7,6,3,4,1,2]
[1,2,3,4,5,6,7]
#匿名函数写法
L=[('b',2),('a',1),('c',3),('d',4)]
#利用参数cmp排序
sorted(L,cmp=lambda x,y:cmp(x[1],y[1])) #两个参数
#利用参数key排序
sorted(L,key=lambda x:x[1]) #一个参数
#结果:
[('a',1),('b',2),('c',3),('d',4)]
#按年龄升序
students = [('john','A',15),('jane','B',12),('dave','B',10)]
sorted(students,key=lambda s:s[2])
#结果:
[('dave','B',10),('jane','B',12),('john','A',15)]
#按年龄降序
sorted(students,key=lambda s:s[2],reverse=True)
#结果:
[('john','A',15),('jane','B',12),('dave','B',10)]
利用参数cmp比较不好理解
• filter()函数
描述:用于过滤序列,过滤掉不符合条件的元素,返回由符合条件的元素组成的新列表
语法:filter(function,iterable)
参数:function是一个判断函数;iterable是可迭代对象
返回值:Python2.7返回列表,Python3.x返回迭代器对象
#一般写法
#过滤出列表的所有奇数
def is_odd(n):
return n % 2 == 1
newlist = filter(is_odd,[1,2,3,4,5,6,7,8,9,10])
print(list(newlist))
#结果:
[1,3,5,7,9]
#匿名函数写法
#将列表[1,2,3]中能够被3整除的元素过滤出来
newlist = filter(lambda x:x % 3 == 0,[1,2,3])
print(list(newlist))
#结果:
[3]
四、学习的思考与总结
1、task2的学习遇到了很多不认识的函数,在函数的学习上花费了大量的时间。有些函数一个可以带出好几个也有好几种用法,学习的过程中会显得更吃力了一些。
2、task2的学习没有在开启打卡的第一天就开始,直到24号才开始学习,明显发现赶不上进度,下一个task一定要按时开始,避免拖到最后导致效率降低。
3、成为大佬的道路上真的是艰难险阻ヽ(*。>Д<)o゜,加油吧!!!