在这个章节里,进行的是对数据的清洗、重构和可视化的操作。
2.1.1 任务一:缺失值观察
import numpy as np
import pandas as pd
df=pd.read_csv('train.csv')
df.head()
#方法一
df.info()
#方法二
df.isnull().sum()
2.1.2 任务二:对缺失值进行处理
(1)利用np.nan
,None
以及.isnull()
检索空缺值
df[df['Age']==None]=0
df['Age']
#发现还有缺失值
df[df['Age']==np.nan]
#发现还有缺失值
df[df['Age'].isnull()]=0
df['Age']
#发现没有缺失值了
思考:检索空缺值用np.nan
,None
以及.isnull()
哪个更好?
在用pandas和numpy处理数据阶段将None,np.nan统一处理成np.nan,以便支持更多的函数,所以np.nan更好
(2)使用fillna函数
df['Age'].fillna(0)#用0替换缺失值
df['Age'].fillna(method="ffill")#用前一个的值替换缺失值
values = {"Age":1,"Fare":0}#可以同时替换不同的列
df.fillna(value=values)
df['Age'].fillna(value=values,limit=1)#只替换第一个缺失值
(3)使用dropna函数
df.dropna()#只要有一个缺失值就删掉
df.dropna(axis='columns')#保留没有缺失值的列
df.dropna(how='all')#只删掉所有的值都是缺失值的行
df.dropna(thresh=2)#删掉有两个缺失值的行
df.dropna(subset=['Age','Cabin'])#删掉特定子集有缺失值的行
df.dropna(inplace=True)#只保留所有值都是有效的值
df
2.2.1 任务一:请查看数据中的重复值
df[df.duplicated()]
2.2.2 任务二:对重复值进行处理
df=df.drop_duplicates()
df=df.drop_duplicates(['Age'])
2.2.3 任务三:将前面清洗的数据保存为csv格式
f.to_csv('test_clear.csv')
泰坦尼克号的数据可以分为两类,分别是离散型、连续型数据。
又可以分为:
数值型特征:Survived ,Pclass, Age ,SibSp, Parch, Fare,其中Survived, Pclass为离散型数值特征,Age,SibSp, Parch, Fare为连续型数值特征
文本型特征:Name, Sex, Cabin,Embarked, Ticket,其中Sex, Cabin, Embarked, Ticket为类别型文本特征,数值型特征一般可以直接用于模型的训练,但有时候为了模型的稳定性及鲁棒性会对连续变量进行离散化。文本型特征往往需要转换成数值型特征才能用于建模分析。
2.3.1 任务一:对年龄进行分箱(离散化)处理
(1)分箱操作是什么?
分箱操作就是对连续变量离散化,特征离散化后,模型会更稳定,降低了模型过拟合的风险,分箱操作有等距划分、等频划分
pandas.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False)
x,类array对象,且必须为一维,待切割的原形式
bins, 整数、序列尺度、或间隔索引。如果bins是一个整数,它定义了x宽度范围内的等宽面元数量,但是在这种情况下,x的范围在每个边上被延长1%,以保证包括x的最小值或最大值。如果bin是序列,它定义了允许非均匀in宽度的bin边缘。在这种情况下没有x的范围的扩展。
right,布尔值。是否是左开右闭区间
labels,用作结果箱的标签。必须与结果箱相同长度。如果FALSE,只返回整数指标面元。
retbins,布尔值。是否返回面元
precision,整数。返回面元的小数点几位
include_lowest,布尔值。第一个区间的左端点是否包含
(2) 将连续变量Age平均分箱成5个年龄段,并分别用类别变量12345表示
df['AgeBand']=pd.cut(df['Age'],5,labels=[1,2,3,4,5])
df.to_csv("test_ave.csv")
(3) 将连续变量Age划分为[0,5) [5,15) [15,30) [30,50) [50,80)五个年龄段,并分别用类别变量12345表示
df['AgeBand']=pd.cut(df['Age'],[0,5,15,30,50,80],labels=[1,2,3,4,5])
df.to_csv('test_cut.csv')
(4) 将连续变量Age按10% 30% 50% 70% 90%五个年龄段,并用分类变量12345表示
df['AgeBand']=pd.qcut(df['Age'],[0,0.1,0.3,0.5,0.7,0.9],labels=[1,2,3,4,5])#基于分位数的离散化功能
df
2.3.2 任务二:对文本变量进行转换
(1) 查看文本变量名及种类
#方法一:
df['Sex'].value_counts()
df['Cabin'].value_counts()
df['Embarked'].value_counts()
#方法二:
df['Sex'].unique()
df['Sex'].nunique()
(2) 将文本变量Sex, Cabin ,Embarked用数值变量12345表示
#方法一: replace
df['Sex_num']=df['Sex'].replace(['male','female'],[1,2])
df
#方法二:map
df['Sex_num']=df['Sex'].map({'male':1,'female':2})
df
(3) 将文本变量Sex, Cabin, Embarked用one-hot编码表示
for feat in ["Age", "Embarked"]:
x = pd.get_dummies(df[feat], prefix=feat)
df = pd.concat([df, x], axis=1)
#df[feat] = pd.get_dummies(df[feat], prefix=feat)
2.3.3 任务三:从纯文本Name特征里提取出Titles的特征(所谓的Titles就是Mr,Miss,Mrs等)¶
df['Title']=df.Name.str.extract(' ([A-Za-z]+)\.',expand=False)
#为了提取Mr,可以看到Mr前面有空格,且从大写字母开始再到小写字母 。
#所以该正则表达式也是类似:先空了一格,从大写字母A-Z中匹配,再从小写字母a-z中匹配, 到 .(点)这里结束。
#\表示转义,在正则表达式中点(.)表示:匹配除换行符 \n 之外的任何单字符。若要直接使用则需要加上转义符号
第二节数据重构
2.4.1方法一:使用concat方法
list_up=[text_left_up,text_right_up]
result_up=pd.concat(list_up,axis=1)#列合并
result_up
list_down=[text_left_down,text_right_down]
result_down=pd.concat(list_down,axis=1)
result_down
list=[result_up,result_down]
result=pd.concat(list,axis=0)
result
2.4.2方法二:使用DataFrame自带的方法join方法和append方法
result_up=text_left_up.join(text_right_up)#join是列合并
result_up
result_down=text_left_down.join(text_right_down)
result=result_up.append(result_down)#append是行合并
result
2.4.3方法三:使用Panads的merge方法和DataFrame的append方法
result_up=pd.merge(text_left_up,text_right_up,left_index=True,right_index=True)
result_up
result_down=pd.merge(text_left_down,text_right_down,left_index=True,right_index=True)
result_down
result=result_up.append(result_down)
result
2.5.1 任务一:将我们的数据变为Series类型的数据
text=pd.read_csv('result.csv')
text
unit_result=text.stack()
unit_result
unit_result.to_csv('unit_result.csv')
text=pd.read_csv('unit_result.csv')
text
2.6 数据运用
2.6.1任务一:
了解GroupBy机制
df[](指输出数据的结果属性名称).groupby([df[属性],df[属性])(指分类的属性,数据的限定定语,可以有多个).mean()(对于数据的计算方式——函数名称)
company=['A','B','C']
data=pd.DataFrame({"company":[company[x] for x in np.random.randint(0,len(company),10)],
"salary":np.random.randint(5,50,10),
"age":np.random.randint(15,50,10)})
data
group = data.groupby("company")
list(group)
#groupby之后的常见操作
data.groupby("company").agg('mean')#求不同公司员工的平均年龄和平均薪水
data.groupby("company").agg({"salary":"median","age":"mean"})#要计算不同公司员工的平均年龄以及薪水的中位数
#新增一列avg_salary,代表员工所在的公司的平均薪水
data['avg_salary']=data.groupby('company')['salary'].transform('mean')#方法一
avg_salary_dict=data.groupby('company')['salary'].mean().to_dict()#方法二先求得不同公司的平均薪水,然后按照员工和公司的对应关系填充到对应的位置
data['avg_salary']=data['company'].map(avg_salary_dict)
data
def get_oldest_staff(x):
df=x.sort_values(by='age',ascending=True)
return df.iloc[-1,:]
oldest_staff=data.groupby('company',as_index=False).apply(get_oldest_staff)
oldest_staff
2.6.2任务二:计算泰坦尼克号男性与女性的平均票价
means=df.groupby('Sex')['Fare'].mean()
means
2.6.3:任务三:统计泰坦尼克号中男女的存活人数
survived_sex=df.groupby('Sex')['Survived'].sum()
survived_sex
2.6.4:任务四:计算客舱不同等级的存活人数
df.groupby('Pclass')['Survived'].sum()
【思考】从任务二到任务三中,这些运算可以通过agg()函数来同时计算。并且可以使用rename函数修改列名
df.groupby('Sex').agg({"Fare":'mean','Pclass':'count'}).rename(columns={'Fare':'mean_fare','Pclass': 'count_pclass'})
2.6.5:任务五:统计在不同等级的票中的不同年龄的船票花费的平均值
df.groupby(['Pclass','Age'])['Fare'].mean()
2.6.6:任务六:将任务二和任务三的数据合并,并保存到sex_fare_survived.csv
result=pd.merge(means,survived_sex,on='Sex')
result
2.6.7:任务七:得出不同年龄的总的存活人数,然后找出存活人数的最高的年龄,最后计算存活人数最高的存活率(存活人数/总人数)
survived_age=df.groupby('Age')['Survived'].sum()
survived_age[survived_age.values==survived_age.max()]
_sum=df['Survived'].sum()
precetn=survived_age.max()/_sum
print("总人数:"+str(_sum))
precetn
print("最大存活率:"+str(precetn))