【TL第二期】动手学数据分析-第二章 数据预处理

8 篇文章 0 订阅
7 篇文章 0 订阅

第二章

第一节 数据清洗及特征处理

数据清洗:对于原始数据中的缺失值、异常值进行处理。相当于数据预处理

待处理的情况:缺失值、重复值、字符串和数据转换。

  1. 缺失值

    如何查看各列缺失值的情况:

    df.info()
    # 可以查看每一列数据的缺失值情况,及数据类型
    
    df.isnull()
    # 查看数据表的哪些值是缺失的
    
    df.isnull().sum()
    # 直接统计缺失情况
    
    

    检索缺失值:

    # 查看Age、Cabin、Embarked列的数据
    df[['Age','Cabin','Embarked']].head() 
    
    # 检索空缺值的三种方式
    df[df['Age']==None]=0
    
    df[df['Age'].isnull()]=0
    
    df[df['Age']==np.nan]=0
    
    # 最好使用np.nan。当空缺值的数据类型为float64所以用None索引不到
    

    处理缺失值:

    # 方法一:去除存在缺失值的项
    df.dropna()
    
    # 方法二:使用 0 补全
    # df.fillna({'Age':0})
    # 该方法中,df本身不会发生改变,因此对其赋值得到新的数据
    df = df.fillna({'Age':0})
    
    # 方法三:使用 0 补全(由条件判断进行补全)
    df.loc[df['Age'].isnull(),'Age'] = 0
    # loc函数表示行,即Age一列的哪一行为空,即补0
    

    对整张表的缺失值进行补0处理

    df.fillna(0)
    
  2. 重复行

    对于整个数据集,可能存在有两条(两行)数据是完全相同的。

    # 重复行检索
    df.duplicated() # 给出每一条数据是否重复的结果
    df[df.duplicated()] # 单独显示重复的数据
    
    # 删除重复行
    df = df.drop_duplicates()
    
  3. 特征观察与处理

    数据特征的分类:

    • 数值型:分为离散型和连续型。一般可以直接用于模型的训练。但有时为了模型的稳定性,困难会将离散型变量转换为连续变量。
    • 文本型:文本型特征 往往需要转换成数值型特征才可以用于建模分析。

    ① 分箱处理(离散化处理)

    例:本案例中,将年龄【连续 -->离散】分为五个阶段,每个阶段用一个值来代替。

    • 年龄均分cut()

      # 将数据按年龄平均分为5个部分:
      # df['AgeBand'] = pd.cut(df['Age'], 5,labels = [1,2,3,4,5])
      # df['AgeBand'] = pd.cut(df['Age'], 5,labels = list('12345'))
      df['AgeBand'] = pd.cut(df['Age'],[0,5,15,30,50,80],right=False)
      
      # cut函数的三个参数:bins()、right(区间是右闭还是右开,默认为True,左开右闭)、labels
      

      分箱操作的优点:

      能适应异常值的存在。以年龄为例,若出现300岁的异常数据,分箱之后只会进入最大的分组,而不会通过大数据影响模型。

    • 年龄按百分比分类qcut()

      # 按10%、30%、50%、70%、90%分为5个年龄段
      df['AgeBand'] = pd.qcut(df['Age'],duplicates = 'drop',[0,0.1,0.3,0.5,0.7,0.9],labels = list('1234'))
      
      # duplicates参数:边缘是否唯一(默认为raise,唯一;否则为drop)
      

    ②对文本变量进行转换

    • 查看文本变量的种类

      # 方法一
      # 可以查看每一列数据的每一种文本的种类
      df.['Sex'].value_counts()
      
    # 方法二
    df.['Cabin'].unique()
    

    image-20211220111404269

    • 转为数值变量

      # 对于文本种类不多的列
      # 方法一:直接用`replace()`替换
      df['Sex'].replace(['male','female'],[1,2], inplace = True) # inplace=True,直接作用于当前文件本身
      
      #方法二: map,字典
      df['Sex_num'] = df['Sex'].map({'male': 1, 'female': 2})
      
      # 对于文本种类过多的列
      # 使用sklearn.preprocessing的LabelEncoder
      from sklearn.preprocessing import LabelEncoder
      df['Cabin'] = LabelEncoder().fit_transform(df['Cabin'])
      
    • 将类别文本转换为one-hot编码

      若按数值简单对文本进行处理,数值之间的大小没有任何意义,故采用one-hot编码

      image-20211220112139965

      #方法一: OneHotEncoder
      x = pd.get_dummies(df['Age'], prefix='Age')
      # 将变换好的年龄数据拼接到原始数据上
      df = pd.concat([df, x], axis=1) # 按列拼接
      
      # 进阶:使用循环进行批量处理
      for column in ['Cabin', 'Age', 'Embarked']
      	x = pd.get_dummies(df[column], prefix=column)
          df = pd.concat([df, x], axis=1) 
      

      one-hot编码中只有0、1,且大部分都是0,因此很有利于提高计算性能。

    ③【附加问题】从纯文本Name特征里提取出Titles的特征(所谓的Titles就是Mr,Miss,Mrs等)

    df['Title'] = df.Name.str.extract('([A-Za-z]+)\.', expand=False)
    
    # 参数:正则表达式
    

第二节 数据重构1

数据重构仍属于数据准备(数据预处理)的范围。

  1. 数据的合并

    • concat()

      横向合并:对于两张表,如果属于左部、右部的不同列的数据,使用concat()方法进行数据合并。

      list_up = [text_left_up,text_right_up] # 两个待合并的数据
      result_up = pd.concat(list_up,axis=1) # axis=1, 横向合并(该参数默认为0)
      
      list_down=[text_left_down,text_right_down]
      result_down = pd.concat(list_down,axis=1)
      

      纵向合并:

      result = pd.concat([result_up,result_down]) # axis的值默认为0,表示纵向合并
      
    • DataFrame自带的join()append

      # join()相当于concat()的横向合并;append()相当于concat()的纵向合并,即concat()默认方法。
      up = text_left_up.join(text_right_up)
      down = text_left_down.join(text_right_down)
      
      result = up.append(down)
      
    • Pandas的merge()和DataFrame的append()

      # merge()类似于join(),但额外需要一个共同的列用于拼接,即显示行索引(相同的列)
      up = text_left_up.merge(text_right_up, left_index = True, right_index = True)
      down = text_left_down.merge(text_right_down, left_index = True, right_index = True)
      
      result = up.append(down)
      

      三者对比:

      concat()可以用于实现行、列的拼接,需要改变的是参数axis的值,默认使用按行拼接(axis = 0);

      join()merge()都只能用于按列拼接,且merge()的使用多了一个步骤;

      append()只能用于按行拼接。

  2. 另一种数据类型 - Series

    stackunstack函数:改变数据集的样式,返回一个重构的数据

    image-20211220191801865

    data2 = data.stack() # 将表格变为“花括号”形式
    data3 = data2.unstack() # 将“花括号”形式变为二维表格形式
    

    image-20211217233552775

    img

    输出到本地之后的格式:

    img


第三节 数据重构2
  1. 数据运用

    GroupBy机制(分组机制:分隔、应用和组合)

    分组之后进行更高一级的运算:最大、小值,求和,均值,中位数,标准差,方差

    分组机制拓展:

    my_group1=titanic.groupby('pclass') #将数据对乘客所在船舱等级(“pclass”)进行分组
    # 此时数据不再是DataFrame对象,而是DataFrameGroupBy对象.
    my_group1.count() #据此对分组后的数据进行分析
    
    # 或者使用list()来查看每一个group
    list(my_group1)
    
    # 以不同性别下的存活情况为例,输出存活率与存活人数
    my_group2=titanic.groupby('sex')
    sex_sur=my_group2['survived'].agg(['mean','count']) # 通过传入agg方法选择所需的函数
    sex_sur
    
    # 可以实现多层分组
    my_group2=titanic.groupby(['pclass','sex'])
    my_group2.agg(['mean','count'])
    

    上述代码运行的结果展示:【多层分组】

    img

    # 对方法重命名,方便理解
    my_group2=titanic.groupby(['pclass','sex'])
    my_group2.agg([('均值','mean'),('计数','count')])
    

    img

    ① 计算泰坦尼克号男性与女性的平均票价

    group = df.groupby('Sex')
    group.describe() # 显示性别分类下所有属性的详情
    

    image-20211220192703495

    df.groupby('Sex')['Age'].describe() # 加上年龄标签,显示性别分类下的年龄情况
    

    image-20211220192815939

    df.groupby('Sex')['Age'].mean() # 显示性别分类下的年龄平均值
    
    df.groupby('Sex')['Fare'].mean() # 显示性别分类下的票价平均值
    

    image-20211220192851006

    ② 统计泰坦尼克号中男女的存活人数

    survived_sex = df.groupby('Sex')['Survived'].sum()
    

    ③ 计算客舱不同等级的存活人数

    survived_pclass = df.groupby('Pclass')['Survived'].sum()
    

    这些运算可以通过agg()函数来同时计算。并且可以使用rename()函数修改列名。

    方便同时统计多个维度的数据。否则需要经过多次的数据合并,较复杂。

    # agg()函数:可以指定多个计算方法
    df.groupby('Pclass')['Survived'].agg('sum') # 与上面的结果相同,没有区别
    
    df.df.groupby('Pclass').agg({'Survived':'sum', 'Fare':'mean'}) # 同时对存活人数求和、对票价取平均
    

    image-20211220193831646

    # 对于上述计算,为了更直观地进行结果展示,使用rename()函数进行处理
    df.df.groupby('Pclass').agg({'Survived':'sum', 'Fare':'mean'}).rename(columns = {
        'Survived':'survived_sum','Fare':'fare_mean'
    })
    

    ④统计在不同等级的票中的不同年龄的船票花费的平均值

    df.groupby(['Pclass','Age'])['Fare'].mean() # 根据两列进行分类,再统计票价的平均值
    

    ⑤ 将①、②数据合并

    result = pd.merge(means,survived_sex, on='Sex')
    

    image-20211218000504907

    merge()不可以直接对Series格式的数据进行拼接,需要转为DataFrame格式

    survived_sex.to_frame() # 即可将Series格式转为DataFrame格式
    

    ⑥ 得出不同年龄的总的存活人数,然后找出存活人数最多的年龄段,最后计算存活人数最高的存活率(存活人数/总人数)

    #不同年龄的存活人数
    survived_age = df.groupby('Age')['Survived'].sum()
    
    #找出最大值的年龄段
    survived_age[survived_age.values == survived_age.max()] # values指当前键对应的数据的条数
    
    #首先计算存活总人数
    _sum = df['Survived'].sum()
    
    percent =survived_age.max()/_su
    

第四节 数据可视化

Matplotlib:Python数据可视化库

绘图方法总结:

plot()默认是折线图;

hist()直方图;

%matplotlib inline
import matplotlib.pyplot as plt

# from matplotlib import pyplot as plt

展示泰坦尼克号数据集中男女中生存人数分布情况(柱状图)

sex = df.groupby('Sex')['Survived'].sum()
sex.plot.bar()

plt.title('survived_count')
plt.show()

image-20211218110908861

男女中生存人与死亡人数的比例图(柱状图)

df.groupby(['Sex','Survived'])['Survived'].count().unstack().plot(kind='bar',stacked='True')
plt.title('survived_count')
plt.ylabel('count')

# 使用Sex、Survived同时作为分类条件,可以同时获取生存人数和死亡人数
# count():分别计数
# unstack() 将数据变为二维表格的形式
# 0表示死亡,1表示生存

image-20211218111215605

不同票价的人生存和死亡人数分布情况(折线图)

# 计算不同票价中生存与死亡人数 1表示生存,0表示死亡
fare_sur = df.groupby(['Fare'])['Survived'].value_counts().sort_values(ascending=False)
fare_sur

image-20211218111513374

# 排序后绘折线图
fig = plt.figure(figsize=(20, 18))
fare_sur.plot(grid=True)
plt.legend()
plt.show()

image-20211218111538940

票价高的人死亡比例低

不同仓位等级的人生存和死亡人员的分布情况(柱状图)

# 1表示生存,0表示死亡
pclass_sur = df.groupby(['Pclass','Survived'])['Survived'].counts().unstack()

不同年龄的人生存与死亡人数分布情况

# 死亡人数
df.Age[df.Survived == 0].hist(bins=5, alpha=0.5) # 绘制直方图

# 生存人数 
df.Age[df.Survived == 1].hist(bins=5, alpha=0.5) # alpha参数:更改透明度

plt.legend({0,1})
plot.xlabel('age')
plot.ylabel('count')

image-20211220201959590

# density参数:根据分布密度绘制直方图。
# 会改变纵坐标刻度,变为密度
df.Age[df.Survived == 0].hist(bins=5, alpha=0.5, density=1) 
df.Age[df.Survived == 1].hist(bins=5, alpha=0.5, density=1)
df.Age[df.Survived == 1].plot.density() # 增加密度曲线
df.Age[df.Survived == 0].plot.density()
plt.legend({0,1})
plot.xlabel('age')
plot.ylabel('density')

image-20211220202300804

不同仓位等级的人年龄分布情况(折线图)

# 方法一
df.Age[df.Pclass == 1].plot(kind='kde')
df.Age[df.Pclass == 2].plot(kind='kde')
df.Age[df.Pclass == 3].plot(kind='kde')
plt.xlabel("age")
plt.legend((1,2,3),loc="best")

image-20211218111934354

# 方法二
unique_pclass = df.Pclass.unique()
unique_pclass.sort() # 对获得的数值进行排序
for i in unique_pclass:
    df.Age[df.Pclass == i].plot.density()
plt.xlabel('age')
plt.legend(unique_pclass)
# 方法三
import seaborn as sns
for i in unique_pclass:
    sns.kdeplot(df.Age[df.Pclass == i], shade=True, linewidth=0)

image-20211220204406454


the end.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值