【经典永不过时】数据分析网红级别的项目案例分享【超详细】

大家早上好,本人姓吴,如果觉得文章写得还行的话也可以叫我吴老师。欢迎大家跟我一起走进数据分析的世界,一起学习!

本周给大家分享的数据分析案例是泰坦尼克号幸存者预测的项目,没记错的话,这应该是很多朋友写在简历上的项目经历。如果你目前正在找工作,自身缺少项目经历并且想要充实项目经历的话,可以考虑一下这个项目!

完整文本介绍、代码以及数据集下载链接放在文末!

目录

泰坦尼克号幸存者预测

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn import linear_model
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import Perceptron
from sklearn.linear_model import SGDClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC, LinearSVC
from sklearn.naive_bayes import GaussianNB

%matplotlib inline

1 获取数据集

读取参数指定的文件,返回一个DataFrame类型的对象。

有两个数据集:训练集和测试集。 我们将使用训练集来构建我们的预测模型,用测试集来对其进行评分并生成输出文件以在Kaggle评估系统上提交。

test_df = pd.read_csv("./test.csv")
train_df = pd.read_csv("./train.csv")

1.1 探索性数据分析

开始探索数据,带着问题去理解数据。

通过以下的属性和方法了解数据

  • 属性
  • df.columns.value 数据集中所有列名(特征),numpy.ndarray 类型
  • 方法
  • df.head() 预览数据集前5行
  • df.tail() 预览数据集后5行
  • df.info() 显示大致数据信息,包括每列名称,非空值数量,每列的数据类型,内存占用等信息。
  • df.describe() 展示数据的一些描述性统计信息,但会过滤掉缺失值。默认只统计数值类型的字段内容。
    • describe(include=‘ALL‘),统计所有类型的数据
    • describe(include=[np.number]) 只统计数值类型的字段内容:count计数,mean平均数,std方差,min最小值,四分位数,max 最大值
    • describe(include=[np.object]) 只统计object类型的字段内容
    • describe(include='O') 只统计字符串类型的字段内容:count计数,unique唯一值数量,top出现频率最高的内容,freq最高出现频率</li> <li><code>describe(percentiles=[])</code>:设置输出的百分位数,默认为[.25,.5,.75],返回第25,第50和第75百分位数。</li> </ul> </li> </ul> <h3>1.1.1 预览数据</h3> <ul> <li><code>df.head()</code> 预览数据集前5行</li> </ul> <pre><code class="language-python">train_df.head() </code></pre> <p>PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S4503Allen, Mr. William Henrymale35.0003734508.0500NaNS</p> <p><strong>Survived 列是目标变量,这是我们要预测的变量。</strong> 如果 Survived 为 1,乘客幸免于难,为 0,表示未存活。</p> <p>Survived是否存活0死亡1存活</p> <p>其他描述乘客的变量,是 <strong>特征</strong>。</p> <p>数据特征意思PassengerId乘客IDPclass乘客等级(1,2,3)Name乘客姓名Sex乘客性别 (Female,Male)Age乘客年龄SibSp与乘客同行的兄弟姐妹和配偶的数量Parch与乘客同行的父母和孩子的数量Ticket船票号码Fare票价Cabin船舱号码Embarked乘客登船港口(C = Cherbourg, Q = Queenstown, S = Southampton)</p> <h3>1.1.2 数据集的大致信息</h3> <p><code>df.info()</code> 显示大致数据信息,包括每列名称,非空值数量,每列的数据类型,内存占用</p> <pre><code class="language-python">train_df.info() print('_'*40) test_df.info() </code></pre> <pre><code><class 'pandas.core.frame.dataframe'> RangeIndex: 891 entries, 0 to 890 Data columns (total 12 columns): # Column Non-Null Count Dtype 0 PassengerId 418 non-null int64 1 Pclass 418 non-null int64 2 Name 418 non-null object 3 Sex 418 non-null object 4 Age 332 non-null float64 5 SibSp 418 non-null int64 6 Parch 418 non-null int64 7 Ticket 418 non-null object 8 Fare 417 non-null float64 9 Cabin 91 non-null object 10 Embarked 418 non-null object dtypes: float64(2), int64(4), object(5) memory usage: 36.0+ KB </class></class> </code></pre> <ul> <li>训练数据集</li> <li>行数 : 891个样本大小</li> <li>列数 :12(11个特征+1个 <strong>目标变量 Survived</strong>)</li> <li>数据类型 : 7个特征是整数或浮点数,5个特征是字符串</li> <li>缺失值情况 :Cabin > Age > Embarked (数量从大到小排序)</li> <li>数值型数据 :PassengerId,Age,Fare,SibSp,Parch</li> <li>类别数据 :Survived,Sex,Embarked,Pclass</li> <li>混合型数据:Ticket,Cabin</li> <li>测试数据集</li> <li>列数 :11个特征</li> <li>数据类型 : 6个特征是整数或浮点数,5个特征是字符串</li> <li>缺失值情况 :Cabin > Age > Fare (数量从大到小排序)</li> </ul> <p><strong>知识点</strong></p> <ul> <li><strong>类别数据(定性数据)</strong> 数据被划分为各种类别,用以描述某类得性质或特征。因此,类别数据也称为定性数据。游戏种类就是定性数据的一个实例 —— 每种游戏种类形成一个独立的类别。关于定性数据,请记住一个重点:不能将数据值理解为数字。</li> <li><strong>数值型数据(定量数据)</strong> 数值型数据不同,它所涉及的是数字。数值型数据中的数值具有数字的意义,但还涉及计量或计数。由于数值型数据描述的是数量,所以也称为定量数据。</li> </ul> <h3>1.1.3 数据集的描述性统计信息</h3> <p><code>df.describe()</code> 返回数据数值情况,数值数据的字段内容:count计数,mean平均数,std方差,min最小值,四分位数,max 最大值</p> <pre><code class="language-python">train_df.describe() </code></pre> <p>PassengerIdSurvivedPclassAgeSibSpParchFarecount891.000000891.000000891.000000714.000000891.000000891.000000891.000000mean446.0000000.3838382.30864229.6991180.5230080.38159432.204208std257.3538420.4865920.83607114.5264971.1027430.80605749.693429min1.0000000.0000001.0000000.4200000.0000000.0000000.00000025%223.5000000.0000002.00000020.1250000.0000000.0000007.91040050%446.0000000.0000003.00000028.0000000.0000000.00000014.45420075%668.5000001.0000003.00000038.0000001.0000000.00000031.000000max891.0000001.0000003.00000080.0000008.0000006.000000512.329200</p> <ul> <li>Survied 的均值为 0.383838,而 survied 值只有0或1,说明这个均值反应了存活率。</li> <li>样本存活率约38%,实际存活率为32%(2224-1502/2224=32.4%)</li> </ul> <p>从目前来看,要注意几点。</p> <ul> <li>需要将非数值型特征转换为数值型特征,以便机器学习算法后期处理。</li> <li>这些特征的范围有很大的差异,需要将其转换为大致相同的尺度。</li> <li>一些特征包含缺失值(NaN = 不是数字),们需要处理。</li> </ul> <h3>1.1.4 数据集缺失值详情</h3> <ul> <li><code>df.isnull()</code> 返回表明哪些值是缺失值的布尔值</li> <li><code>df.notnull()</code> 返回表明哪些值不是缺失值的布尔值</li> <li><code>df.dropna()</code> 根据每个标签的值是否是缺失数据来筛选轴标签,并根据允许丢失的数据量来确定阀值</li> <li><code>df.sort_values()</code> 排序,默认升序,ascending = False表示降序</li> <li><code>pd.concat([])</code> 使对象在轴向上进行粘合或"堆叠",默认是沿着 axis=0(行) 的轴向。axis=1 表示(列)的轴向。</li> <li><code>round(x[, n])</code> 方法返回浮点数x的四舍五入值,n小数点位数</li> </ul> <pre><code class="language-python">train_total = train_df.isnull().sum().sort_values(ascending=False) percent_1 = train_df.isnull().sum()/train_df.isnull().count()*100 percent_2 = round(percent_1,1).sort_values(ascending=False) train_miss_data = pd.concat([train_total,percent_2],axis=1,keys=['total','%']) train_miss_data.head() </code></pre> <p>total%Cabin68777.1Age17719.9Embarked20.2Fare00.0Ticket00.0</p> <pre><code class="language-python">test_total = test_df.isnull().sum().sort_values(ascending=False) percent_1 = test_df.isnull().sum()/test_df.isnull().count()*100 percent_2 = round(percent_1,1).sort_values(ascending=False) test_miss_data = pd.concat([test_total,percent_2],axis=1,keys=['total','%']) test_miss_data.head() </code></pre> <p>total%Cabin32778.2Age8620.6Fare10.2Embarked00.0Ticket00.0</p> <ul> <li>训练数据集</li> <li>Embarked 特征只有2个缺失的值,可以很容易地填补。</li> <li>Age 特征就比较麻烦了,因为它有177个缺失值。</li> <li>Cabin 特征需要进一步调查,但看起来可能要从数据集中删除它,因为缺失值比例高达 77%。</li> <li>测试数据集</li> <li>Fare 特征只有1个缺失的值,可以很容易地填补。</li> <li>Age 特征有86个缺失值。</li> <li>Cabin 特征需要进一步调查,但看起来可能要从数据集中删除它,因为缺失值比例高达 78.2%。</li> </ul> <p>isnull用法</p> <ul> <li>df.isnull() #元素为空或者NA就显示True,否则就是False</li> <li>df.isnull().any() #判断哪些列包含缺失值,该列存在缺失值则返回True,反之False。</li> </ul> <p>对比count() 、isnull().count()和isnull().sum()</p> <ul> <li>df.count() #每一列中非缺失值的个数</li> <li>df.isnull().count() #每一列总元素个数</li> <li>df.isnull().sum() #每列缺失数据的个数</li> </ul> <h3>1.1.5 假设</h3> <p><strong>哪些特征可能和存活有关?</strong></p> <pre><code class="language-python">train_df.columns.values </code></pre> <pre><code>array(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp', 'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'], dtype=object) </code></pre> <p>初步判断,除了PassengerId、Ticket和 Name之外,其他特征都可能与存活有关。</p> <h4>1.1.5.1 数值型 Age、类别型 Sex、类别型 Survived 三者之间的关系:</h4> <ul> <li>首先将数据按照性别(Female, Male)划分</li> <li>基于性别,再根据存活状态(Survived,Not_Survived)划分</li> <li>就会有四种搭配</li> <li>Female & Survived</li> <li>Female & Not_Survived</li> <li>Male & Survived</li> <li>Male & Not_Survived</li> <li>鉴于 Age 特征有缺失值,在此处可视化分析时,需要去除 Age 的缺失值</li> </ul> <pre><code class="language-python"> women = train_df[train_df['Sex']=='female'] men = train_df[train_df['Sex']=='male'] F_survived = women[women['Survived']==1] M_survived = men[men['Survived']==1] F_not_surv = women[women['Survived']==0] M_not_surv = men[men['Survived']==0] F_survived.head() </code></pre> <p>PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S8913Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)female27.00234774211.1333NaNS91012Nasser, Mrs. Nicholas (Adele Achem)female14.01023773630.0708NaNC</p> <p>求某一列的缺失值情况</p> <p>由于 Dataframe 数据中选择某一列的方式有 (按照字典型标记或属性那样检索为 Series) - df.A 的属性方式 - df['A'] 的方式 所以求某一列的缺失值情况也有两种 - df.A.isnull().sum() - df['A'].isnull().sum()</p> <p>根据某一列去除缺失值 - df.A.isnull().dropna() - df['A'].isnull().dropna()</p> <pre><code class="language-python"> print('去除前,Female survived null', F_survived.Age.isnull().sum()) F_survived.Age.dropna() M_survived.Age.dropna() F_not_surv.Age.dropna() M_not_surv.Age.dropna() print('取出后,Female survived null',F_survived.Age.dropna().isnull().sum()) </code></pre> <pre><code>去除前,Female survived null 36 取出后,Female survived null 0 </code></pre> <p><strong>知识点</strong></p> <p>displot()集合了matplotlib的hist()与核函数估计kdeplot的功能,增加了rugplot分布观测条显示与利用scipy库fit拟合参数分布的新颖用途。具体用法如下::</p> <pre><code>seaborn.distplot(a, bins=None, hist=True, kde=True, rug=False, fit=None, hist_kws=None, kde_kws=None, rug_kws=None, fit_kws=None, color=None, vertical=False, norm_hist=False, axlabel=None, label=None, ax=None) </code></pre> <pre><code>- 参数 ax:选择位置 - 参数 hist、kde,调节是否显示直方图及核密度估计(默认hist,kde均为True) </code></pre> <p>问题:直方图中参数 bins,这里是根据什么设置的?</p> <ul> <li>极端情况, bins = 1 上图展现了极端情况, 当 bins = 1,表示所有的数据都在一个组内。分组太粗糙影响数据分组规律的明显性,什么都看不出。</li> <li>极端情况, bins = 数据大小 下图进行极端情况的对比, 当 bins = len(data),表示如果所有的数据都不同,将出现和数据长度一样的组。分组太细致会引起较大的误差,因此组数的确定要适当。</li> </ul> <p>组距的宽度:用数据中(最大值-最小值)/组数</p> <pre><code class="language-python">sns.set() fig,axes = plt.subplots(nrows=1,ncols=2,figsize=(16,8)) survived = 'survived' not_survived = 'not survived' ax = sns.distplot(F_survived.Age.dropna(),bins=18,ax=axes[0],kde=False) ax = sns.distplot(F_not_surv.Age.dropna(),bins=40,ax=axes[0],kde=False) ax.legend([survived,not_survived]) ax.set_title('Female') ax = sns.distplot(M_survived.Age.dropna(),bins=18,ax=axes[1],label=survived,kde=False) ax = sns.distplot(M_not_surv.Age.dropna(),bins=40,ax=axes[1],label=not_survived,kde=False) ax.legend() ax.set_title('Male') </code></pre> <pre><code>Text(0.5, 1.0, 'Male') </code></pre> <p><img alt="【经典永不过时】数据分析网红级别的项目案例分享【超详细】" src="https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230619/6e732b7250bd4e9f88ed24809ece81ce.png" /></p> <p>可以看出</p> <ul> <li>对于男性来说,大概20岁到35岁之间的存活率较高的;5岁到18岁之间的存活概率很低,</li> <li>对于女性来说,大概15岁到40岁之间的存活概率更高</li> <li>无论男女,婴儿的存活概率会高一点。</li> </ul> <p>似乎有一些特定的年龄段,存活几率会增加。下面来观察 Age 和 Survived 的关系</p> <h5>1.1.5.1.1 数值型 Age、 类别型 Survived 两者之间的关系</h5> <p>FacetGrid当您想要在数据集的子集中分别可视化变量的分布或多个变量之间的关系时,该类非常有用。一个FacetGrid可以与多达三个维度可以得出:row,col,和hue。前两个与得到的轴阵列有明显的对应关系; 将色调变量视为沿深度轴的第三个维度,其中不同的级别用不同的颜色绘制。</p> <pre><code>FacetGrid(data, row=None, col=None, hue=None, col_wrap=None, sharex=True, sharey=True, height=3, aspect=1, palette=None, row_order=None, col_order=None, hue_order=None, hue_kws=None, dropna=True, legend_out=True, despine=True, margin_titles=False, xlim=None, ylim=None, subplot_kws=None, gridspec_kws=None, size=None) </code></pre> <ul> <li>col 列上的变量(左右)</li> <li>row 行上的变量(上下)</li> </ul> <p>这里将 FacetGrid 函数用于不同存活率的值,独立分成两个直方图。</p> <pre><code class="language-python">import matplotlib.pyplot as plt import seaborn as sns import numpy as np import pandas as pd %matplotlib inline g = sns.FacetGrid(train_df, col='Survived') g.map(plt.hist, 'Age', bins=20) </code></pre> <p><img alt="【经典永不过时】数据分析网红级别的项目案例分享【超详细】" src="https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230619/28eee06040964bbc89fa39aa2913c408.png" /></p> <p>可以看出</p> <ul> <li>婴儿(Age</li> </ul> <h5>1.1.5.1.2 类别型 Sex、 数值型 Survived 两者之间的关系 (这里用的是数值型 Survived,可能需要放到其他位置)</h5> <pre><code class="language-python">import matplotlib.pyplot as plt import seaborn as sns import numpy as np import pandas as pd %matplotlib inline sns.barplot(x='Sex', y='Survived', data=train_df) </code></pre> <p><img alt="【经典永不过时】数据分析网红级别的项目案例分享【超详细】" src="https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230619/d0dfd8f7c7404bf8985e6549085dadba.png" /></p> <p>可以看出,女性乘客的幸存率比男性高。</p> <h4>1.1.5.2 类别型 Embarked、类别型 Pclass、类别型 Sex、数值型 Survived 4者之间的关系</h4> <pre><code class="language-python">grid = sns.FacetGrid(train_df, row='Embarked',height=2.2, aspect=1.6) grid.map(sns.pointplot, 'Pclass', 'Survived','Sex',palette='deep',hue_order=['female','male'],order=[1,2,3]) grid.add_legend() </code></pre> <p><img alt="【经典永不过时】数据分析网红级别的项目案例分享【超详细】" src="https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230619/937f3146b51d4c269f539c09d7df147a.png" /></p> <p>按照性别分类,Embarked 似乎与存活率有关。</p> <ul> <li>不论从哪个港口登船,Pclass 一样的前提下,女性乘客的存活率都高于男性。</li> <li>对于从S或C港口登船的男性乘客中,Pclass=1的存活率比 Pclass =2, Pclass=3 都高。</li> <li>对于从Q港口登船的男性乘客中,Pclass=3的存活率比 Pclass =1, Pclass=2 高。</li> </ul> <p>Pclass 似乎也与存活率有关。下面来观察 Pclass 和 Survived 的关系</p> <h4>1.1.5.3 类别型 Pclass、 数值型 Survived 两者之间的关系</h4> <pre><code class="language-python">sns.barplot(x='Pclass', y='Survived', data=train_df) </code></pre> <p><img alt="【经典永不过时】数据分析网红级别的项目案例分享【超详细】" src="https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230619/b7559e57473e47e9939f7d991ca21e0c.png" /></p> <p>明显可以看出 Pclass=1的乘客存活率更高</p> <h4>1.1.5.4 类别型 Pclass、数值型 Age、 类别型 Survived 三者之间的关系</h4> <p>aspect:每个小图表的横轴长度和纵轴的比,默认为1; height:每个小图表的高度设定,默认为3</p> <pre><code class="language-python">grid = sns.FacetGrid(train_df, col='Survived', row='Pclass', height=2.2, aspect=1.6) grid.map(plt.hist, 'Age', alpha=.5, bins=20) grid.add_legend(); </code></pre> <p><img alt="【经典永不过时】数据分析网红级别的项目案例分享【超详细】" src="https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230619/9abd0b9be2e6404c9fedb8570cfb9718.png" /></p> <pre><code class="language-python"> grid = sns.FacetGrid(train_df,hue='Survived',row='Pclass') grid.map(plt.hist,"Age",bins=20) grid.add_legend() </code></pre> <p><img alt="【经典永不过时】数据分析网红级别的项目案例分享【超详细】" src="https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230619/68a534cbba4e4ce5b8573561c3ef1245.png" /></p> <h4>1.1.5.5 数值型 SibSp、 数值型 Parch、 数值型 Survived 3者之间的关系</h4> <p>SibSp 和 Parch 组合在一起使用才更有意义,组合起来表示与乘客同行的亲属人数。并计算出单独出行和非单独出行的人数</p> <pre><code class="language-python">data = [train_df, test_df] for dataset in data: dataset['relatives'] = dataset['SibSp'] + dataset['Parch'] dataset.loc[dataset['relatives'] > 0, 'not_alone'] = 0 dataset.loc[dataset['relatives'] == 0, 'not_alone'] = 1 dataset['not_alone'] = dataset['not_alone'].astype(int) train_df['not_alone'].value_counts() </code></pre> <pre><code>1 537 0 354 Name: not_alone, dtype: int64 </code></pre> <p>知识点: <strong><a href="https://blog.csdn.net/qq_36523839/article/details/80502574">loc 根据条件,对新增列赋值</a></strong></p> <p><code>df.loc[条件,新增列] = 赋初始值</code></p> <p>如果新增列名为已有列名,则在原来的数据列上改变</p> <pre><code class="language-python">df1 = pd.DataFrame(np.random.rand(8,4),index=list('abcdefgh'),columns=['A','B','C','D']) print(df1) df1.loc[df1['A']<0.5,'小于0.5'] = 1 df1.loc[df1['A']>0.5,'小于0.5'] = 0 print(df1) </code></pre> <pre><code> A B C D a 0.075956 0.513582 0.090774 0.542909 b 0.156261 0.873195 0.974398 0.920191 c 0.015779 0.786579 0.356560 0.604733 d 0.574546 0.742924 0.243504 0.751018 e 0.814584 0.196367 0.067841 0.232922 f 0.480406 0.103638 0.301940 0.153113 g 0.863849 0.479492 0.110800 0.322068 h 0.395352 0.851746 0.858481 0.225225 A B C D 小于0.5 a 0.075956 0.513582 0.090774 0.542909 1.0 b 0.156261 0.873195 0.974398 0.920191 1.0 c 0.015779 0.786579 0.356560 0.604733 1.0 d 0.574546 0.742924 0.243504 0.751018 0.0 e 0.814584 0.196367 0.067841 0.232922 0.0 f 0.480406 0.103638 0.301940 0.153113 1.0 g 0.863849 0.479492 0.110800 0.322068 0.0 h 0.395352 0.851746 0.858481 0.225225 1.0 </code></pre> <p>知识点: <strong>value_counts() 方法</strong></p> <p>返回一个序列 Series,该序列包含每个值的数量。也就是说,对于数据框中的任何列,value-counts () 方法会返回该列每个项的计数。</p> <ul> <li>对该列中出现的每个值进行计数(无效值会被排除) 默认降序排序</li> <li><code>value_counts(ascending=True)</code> 升序</li> <li>求各个值的相对频率</li> <li><code>value_counts(normalize=True)</code></li> </ul> <pre><code class="language-python">df1 = pd.DataFrame(np.random.rand(8,4),index=list('abcdefgh'),columns=['A','B','C','D']) print(df1) df1.loc[df1['A']<0.5,'小于0.5'] = 1 print(df1) print(df1['小于0.5'].value_counts()) df1.loc[df1['A']>0.5,'小于0.5'] = 0 print(df1['小于0.5'].value_counts(normalize=True)) </code></pre> <pre><code> A B C D a 0.387505 0.040494 0.105987 0.320365 b 0.990164 0.930623 0.644406 0.467170 c 0.932130 0.681749 0.080384 0.409407 d 0.985110 0.305801 0.690751 0.145207 e 0.247883 0.645068 0.049671 0.899674 f 0.654758 0.152449 0.750448 0.716139 g 0.753139 0.387617 0.299998 0.236939 h 0.937349 0.227210 0.722307 0.555785 A B C D 小于0.5 a 0.387505 0.040494 0.105987 0.320365 1.0 b 0.990164 0.930623 0.644406 0.467170 NaN c 0.932130 0.681749 0.080384 0.409407 NaN d 0.985110 0.305801 0.690751 0.145207 NaN e 0.247883 0.645068 0.049671 0.899674 1.0 f 0.654758 0.152449 0.750448 0.716139 NaN g 0.753139 0.387617 0.299998 0.236939 NaN h 0.937349 0.227210 0.722307 0.555785 NaN 1.0 2 Name: 小于0.5, dtype: int64 0.0 0.75 1.0 0.25 Name: 小于0.5, dtype: float64 </code></pre> <p>知识点 <strong>astype(int)</strong></p> <p>用于转化dateframe某一列的数据类型</p> <p>如下将dateframe某列的str类型转为int,注意astype()没有replace=True的用法,想要在原数据上修改,要写成如下形式。</p> <p><code>app_train[['uid','index']] = app_train[['uid','index']].astype(int)</code></p> <p>注意只有当该列的字符串全是由纯数字构成时才可以这样写,如果混有字母,会报错:ValueError: invalid literal for int() with base 10</p> <p>利用int()函数转字符串也类似</p> <p>isdigit()用于判断一个字符串是否由纯数字构成,如果是返回True,否则False</p> <pre><code class="language-python">df1['小于0.5'].astype(int).value_counts() </code></pre> <pre><code>0 6 1 2 Name: 小于0.5, dtype: int64 </code></pre> <pre><code class="language-python">grid = sns.catplot('relatives','Survived', data=train_df, kind='point',aspect = 2.5) </code></pre> <p><img alt="【经典永不过时】数据分析网红级别的项目案例分享【超详细】" src="https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230619/ae05c674ff684476a2764e1ec81dda07.png" /></p> <p>观察:</p> <ul> <li>同行家属在1到3位的存活率较高</li> <li>除了6位,同行家属只有1位或者超过3位的存活率较低</li> </ul> <p>决策:</p> <ul> <li>纳入模型</li> </ul> <h2>2 特征工程</h2> <p>训练集和测试集都需要处理,所以将其合并。</p> <p>方法</p> <ul> <li>删除无关特征</li> <li>创建新的特征(根据已有特征,挖掘有效信息创建新的特征)</li> <li>处理缺失值 根据之前我们知晓的缺失值情况,对其一一处理</li> <li>训练数据集<ul> <li>Embarked 特征只有2个缺失的值,可以很容易地填补。</li> <li>Age 特征就比较麻烦了,因为它有177个缺失值。</li> <li>Cabin 特征需要进一步调查,但看起来可能要从数据集中删除它,因为缺失值比例高达 77%。</li> </ul> </li> <li>测试数据集<ul> <li>Fare 特征只有2个缺失的值,可以很容易地填补。</li> <li>Age 特征有86个缺失值。</li> <li>Cabin 特征需要进一步调查,但看起来可能要从数据集中删除它,因为缺失值比例高达 78.2%。</li> </ul> </li> </ul> <pre><code class="language-python"> titanic = train_df.append(test_df, ignore_index=True) passengerId = test_df.PassengerId train_idx = len(train_df) test_idx = len(titanic) - len(test_df) print(titanic.info()) </code></pre> <pre><code><class 'pandas.core.frame.dataframe'> RangeIndex: 1309 entries, 0 to 1308 Data columns (total 14 columns): # Column Non-Null Count Dtype 0 PassengerId 1309 non-null int64 1 Survived 891 non-null float64 2 Pclass 1309 non-null int64 3 Name 1309 non-null object 4 Sex 1309 non-null object 5 Age 1309 non-null float64 6 SibSp 1309 non-null int64 7 Parch 1309 non-null int64 8 Ticket 1309 non-null object 9 Fare 1308 non-null float64 10 Cabin 295 non-null object 11 Embarked 1307 non-null object 12 relatives 1309 non-null int64 13 not_alone 1309 non-null int64 14 Title 1309 non-null object dtypes: float64(3), int64(6), object(6) memory usage: 153.5+ KB </class> </code></pre> <h4>2.3.1 处理特征 Cabin - 创建新的特征:甲板号 (暂时不用这个方法)</h4> <p>之前想直接删除'Cabin'这个特征,但后来我发现了一些有趣的东西。船舱号码'C123',看起来字母代表的是甲板号。因此,我们要提取这些并创建一个新的特征,其中包含一个人的甲板号</p> <ul> <li>fillna 对缺失值进行填充 Pandas 中,缺失数据一般采用 NaN 标记 NaN 代表 Not a Number。特别地,在时间序列里,时间戳的丢失采用 NaT 标记。</li> </ul> <pre><code class="language-python"> train_df['Cabin'] = train_df['Cabin'].fillna("U0") print(list(train_df['Cabin'].map(lambda x: re.compile("([a-zA-Z]+)").search(x).group()).drop_duplicates())) </code></pre> <pre><code>['U', 'C', 'E', 'G', 'D', 'A', 'B', 'F', 'T'] </code></pre> <pre><code class="language-python"> test_df['Cabin'] = test_df['Cabin'].fillna("U0") print(list(test_df['Cabin'].map(lambda x: re.compile("([a-zA-Z]+)").search(x).group()).drop_duplicates())) </code></pre> <pre><code>['U', 'B', 'E', 'A', 'C', 'D', 'F', 'G'] </code></pre> <p>对 NAN 填充"U0",去重,可以看到甲板号,训练集从A到G,然后T,而测试集是从A到G,没有任何不存在于训练集中的夹板号。</p> <p>我们把这个特征转换成一个数字变量。缺少的值将被转换为零。</p> <pre><code class="language-python">import re deck = {"A": 1, "B": 2, "C": 3, "D": 4, "E": 5, "F": 6, "G": 7, "U": 8} titanic['Cabin'] = titanic['Cabin'].fillna("U0") titanic['Deck'] = titanic['Cabin'].map(lambda x: re.compile("([a-zA-Z]+)").search(x).group()) titanic['Deck'] = titanic['Deck'].map(deck) titanic['Deck'] = titanic['Deck'].fillna(0) titanic['Deck'] = titanic['Deck'].astype(int) titanic.info() </code></pre> <pre><code><class 'pandas.core.frame.dataframe'> RangeIndex: 1309 entries, 0 to 1308 Data columns (total 16 columns): # Column Non-Null Count Dtype 0 PassengerId 1309 non-null int64 1 Survived 891 non-null float64 2 Pclass 1309 non-null int64 3 Name 1309 non-null object 4 Sex 1309 non-null object 5 Age 1309 non-null float64 6 SibSp 1309 non-null int64 7 Parch 1309 non-null int64 8 Ticket 1309 non-null object 9 Fare 1309 non-null float64 10 Cabin 1309 non-null object 11 Embarked 1309 non-null object 12 relatives 1309 non-null int64 13 not_alone 1309 non-null int64 14 Title 1309 non-null object 15 Deck 1309 non-null int64 dtypes: float64(3), int64(7), object(6) memory usage: 163.8+ KB </class> </code></pre> <h3>2.4 处理特征 SibSp 和 Parch - 创建新的特征 FamilySize</h3> <pre><code class="language-python"> titanic['FamilySize'] = titanic['Parch'] + titanic['SibSp'] + 1 </code></pre> <h3>2.5 处理特征 Cabin - 创建新的特征 Deck</h3> <p>船舱号码'C123',看起来字母代表的是甲板号。因此,我们要提取这些并创建一个新的特征,其中包含一个人的甲板区域</p> <pre><code class="language-python">titanic['Deck'] = titanic['Cabin'].map(lambda x: x[0]) titanic['Deck'] </code></pre> <pre><code>0 U 1 C 2 U 3 C 4 U .. 1304 U 1305 C 1306 U 1307 U 1308 U Name: Deck, Length: 1309, dtype: object </code></pre> <pre><code class="language-python">titanic.head() </code></pre> <p>PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarkedrelativesnot_aloneTitleDeckFamilySize010.03Braund, Mr. Owen Harrismale22.010A/5 211717.2500U0S10MrU2121.01Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C10MrsC2231.03Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250U0S01MissU1341.01Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S10MrsC2450.03Allen, Mr. William Henrymale35.0003734508.0500U0S01MrU1</p> <h3>2.6 编码</h3> <p>在开始建模之前,我们要执行的最后一步是将我们所有的分类特征转换为数字,因为我们的算法只能接受一个数字数组作为输入,而不是名字或字母。我们有几个列要转换。我们使用Pandas的pd.get_dummies()方法,将分类特征转换为数字特征。</p> <p>Label-Encoding, One-Hot-Encoder 编码区别 <a href="https://towardsdatascience.com/categorical-encoding-using-label-encoding-and-one-hot-encoder-911ef77fb5bd">Categorical encoding using Label-Encoding and One-Hot-Encoder</a></p> <pre><code class="language-python"> titanic['Sex'] = titanic['Sex'].map({"male": 0, "female":1}) pclass_dummies = pd.get_dummies(titanic.Pclass, prefix="Pclass") title_dummies = pd.get_dummies(titanic.Title, prefix="Title") deck_dummies = pd.get_dummies(titanic.Deck, prefix="Deck") embarked_dummies = pd.get_dummies(titanic.Embarked, prefix="Embarked") titanic_dummies = pd.concat([titanic, pclass_dummies, title_dummies, deck_dummies, embarked_dummies], axis=1) titanic_dummies.drop(['Pclass', 'Title', 'Cabin','Deck','Embarked', 'Name', 'Ticket'], axis=1, inplace=True) titanic_dummies.head() </code></pre> <p>PassengerIdSurvivedSexAgeSibSpParchFarerelativesnot_aloneFamilySize...Deck_CDeck_DDeck_EDeck_FDeck_GDeck_TDeck_UEmbarked_CEmbarked_QEmbarked_S010.0022.0107.2500102...0000001001121.0138.01071.2833102...1000000100231.0126.0007.9250011...0000001001341.0135.01053.1000102...1000000001450.0035.0008.0500011...0000001001</p> <p>5 rows × 31 columns</p> <p>我们的数据现在已经是我们需要的格式,使用之前的 train_idx 和 test_idx 索引分离训练集和测试集。</p> <p>还将把训练集分成X,代表预测变量,y 代表我们的目标变量,即 Survived 特征。</p> <ul> <li>?问题:Survived 特征合并前是 int64 的格式,为什么合并后变成了 float64 的格式</li> <li>?问题:警告需要解决</li> </ul> <pre><code class="language-python"> train = titanic_dummies.iloc[ :train_idx] test = titanic_dummies.iloc[test_idx: ] train.Survived = train.Survived.astype(int) x_train = train.drop('Survived', axis=1).values y_train = train.Survived.values x_test = test.drop('Survived', axis=1).values print(train.head()) print(train.info()) </code></pre> <p>
      PassengerId Survived Sex Age SibSp Parch Fare relatives \
      0 1 0 0 22.0 1 0 7.2500 1
      1 2 1 1 38.0 1 0 71.2833 1
      2 3 1 1 26.0 0 0 7.9250 0
      3 4 1 1 35.0 1 0 53.1000 1
      4 5 0 0 35.0 0 0 8.0500 0

      not_alone FamilySize … Deck_C Deck_D Deck_E Deck_F Deck_G Deck_T \
      0 0 2 … 0 0 0 0 0 0
      1 0 2 … 1 0 0 0 0 0
      2 1 1 … 0 0 0 0 0 0
      3 0 2 … 1 0 0 0 0 0
      4 1 1 … 0 0 0 0 0 0

      Deck_U Embarked_C Embarked_Q Embarked_S
      0 1 0 0 1
      1 0 1 0 0
      2 1 0 0 1
      3 0 0 0 1
      4 1 0 0 1

      [5 rows x 31 columns]

      RangeIndex: 891 entries, 0 to 890
      Data columns (total 31 columns):
      # Column Non-Null Count Dtype

      Original: https://blog.csdn.net/qq_44186838/article/details/121593618
      Author: 报告,今天也有好好学习
      Title: 【经典永不过时】数据分析网红级别的项目案例分享【超详细】

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/671378/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球