第6章 数据集成、变换与规约1

编程入门 行业动态 更新时间:2024-10-26 06:29:25

第6章 数据集成、变换与<a href=https://www.elefans.com/category/jswz/34/1737783.html style=规约1"/>

第6章 数据集成、变换与规约1

目录

  • 6. 1 数据集成
    • 6.1.1 数据集成概述
    • 6.1.2 合并数据
      • 6.1.2.1 pandas中用于合并数据的函数与方法
      • 6.1.2.2 主键合并
        • 6.1.2.2.1 pd.merger()
        • 6.1.2.2.2 pd.merge_ordered()
        • 6.1.2.2.3 pd.merge_asof()
      • 6.1.2.3 堆叠合并数据
        • 6.1.2.3.0 构建数据
        • 6.1.2.3.1 pd.concat()
        • 6.1.2.3.2 dataframe.join()
        • 6.1.2.3.3 dataframe.append()
      • 6.1.2.4 重叠合并数据
        • 6.1.2.4.1 dfbine()
        • 6.1.2.4.2 dfbine_first()
      • 6.1.2.5 数据合并应用案例
        • 6.1.2.5.1 读取数据并查看基本信息
        • 6.1.2.5.2 处理缺失值
        • 6.1.2.5.3 合并"student”表与“student_course"表
        • 6.1.2.5.4 合并"student”表与“student_course"表合并的结果与“course”表
  • 6.2 数据变换
    • 6.2.1 数据变换概述
      • 6.2.1.1 数据标准化处理
      • 6.2.1.2 数据离散化处理
      • 6.2.1.3 数据泛化处理
      • 6.2.1.4 Pandas中有关数据变换的基本操作
    • 6.2.2 Pandas 数据标准化处理操作
      • 6.2.2.1 最小-最大标准化(Min-Max Normalization)
      • 6.2.2.2 均值标准化(Z-Score Normalization)
      • 6.2.2.3 小数定标标准化
    • 6.2.3 Pandas数据离散化处理操作
      • 6.2.3.1 时间数据的离散化
      • 6.2.3.2 连续数据的离散化
        • 6.2.3.2.1 距离区间法:自定义分箱区间实现离散化
        • 6.2.3.2.2 频率区间法:按照等频率或指定频率离散化
        • 6.2.3.2.3 聚类法实现离散化
    • 6.2.4 Pandas数据泛化处理操作
    • 6.2.5 Pandas数据变换的其他基本操作
      • 6.2.5.1 Pandas轴向旋转
        • 6.2.5.1.1 pivot()方法
        • 6.2.5.1.2 melt()方法
      • 6.2.5.2 Pandas分组与聚合
        • 6.2.5.2.1 分组操作
        • 6.2.5.2.2 聚合操作
      • 6.2.5.3 Pandas哑变量处理
      • 6.2.5.4 Pandas面元划分
  • 6.3 数据规约
    • 6.3.1 数据规约概述
    • 6.3.2 重塑分层索引
    • 6.3.3 降采样
  • 6.4 案例——中国篮球运动员的基本信息分析

本博客所涉及的jupyter notebook及数据资料请在百度网盘下载

6. 1 数据集成

6.1.1 数据集成概述

数据分析中需要的数据往往来自不同的途径,这些数据的格式、特点、质量千差万别,给数据分析或挖掘增加了难度。为提高数据分析的效率,多个数据源的数据需要合并到一个数据源,形成一致的数据存储,这一过程就是数据集成

在数据集成期间可能会面临很多问题,包括实体识别冗余属性识别元组重复数据值冲突等问题!

  • 实体识别:
    实体识别指从不同数据源中识别出现实世界的实体,主要用于统一不同数据源的矛盾之处,常见的矛盾包括同名异义、异名同义、单位不统一等!

  • 冗余属性识别:
    冗余属性是数据集成期间极易产生的问题,这一问题主要是因为同一属性多次出现、同一属性命名方式不一致造成的。

  • 元组重复:
    元组重复是数据集成期间另一个容易产生的数据冗余问题,这一问题主要是因为录入错误或未及时更新造成的。

由于存在如上问题,数据集成之后可能需要经过数据清理,以便清除可能存在的实体识别、冗余属性识别和元组重复问题。

pandas中有关数据集成的操作是合并数据,并为该操作提供了丰富的函数或方法。

6.1.2 合并数据

6.1.2.1 pandas中用于合并数据的函数与方法

pandas中内置了许多能轻松地合并数据的函数与方法,通过这些函数与方法可以将Series类对象或DataFrame类对象进行符合各种逻辑关系的合并操作,合并后生成一个整合的Series或DataFrame类对象

6.1.2.2 主键合并

主键合并数据类似于关系型数据库的连接操作,主要通过指定一个或多个键将两组数据进行连接,通常以两组数据中重复的列索引为合并键。

6.1.2.2.1 pd.merger()
  • pd.merge()的语法格式
pd.merge(left,   # 待合并的2个数据框                 right,                    how='inner',  # ‘left’, ‘right’, ‘outer’, ‘inner’, ‘cross’                 on=None, # 连接的键,默认是相同的键                        left_on=None,  # 指定不同的连接字段:键不同,但是键的取值有相同的内容                   right_on=None,                 left_index=False,   # 根据索引来连接                   right_index=False,                 sort=False, # 是否排序               suffixes=('_x', '_y'),   # 改变后缀                     copy=True,                           indicator=False,   # 显示字段来源                       validate=None)                    
  • 参数的具体解释为

    • left、right:表示参与合并的Series类对象或DataFrame类对象

    • how:数据合并的方式,有5种:{‘left’, ‘right’, ‘outer’, ‘inner’, ‘cross’}, 默认是 ‘inner’

      • 1、left:左连接,保留left的全部数据,类比于SQL的left join;

      • 2、right:右连接,保留right的全部数据,类比于SQL的right join

      • 3、outer:全连接功能,left与right的数据都将被保留,类似SQL的full outer join

      • 4、inner:基于left合right的共有键的交叉连接,类比于SQL的inner join

      • 5、cross:创建两个数据帧DataFrame的笛卡尔积,默认保留左边的顺序

    • on:连接的列属性;默认是两个DataFrame的相同字段

    • left_on/right_on:指定两个不同的键进行联结

    • left_index、right_index:通过索引进行合并

    • suffixes:指定我们自己想要的后缀

    • indictor:显示字段的来源

  • pd.merge()实例:

# 模拟数据
import pandas as pd
df_left = pd.DataFrame({'key':['K0','K1','K2','K4'],'A':['A0','A1','A2','A3'],'B':['B0','B1','B2','B3']})
df_right = pd.DataFrame({'key':['K0','K1','K2','K3'],'C':['C0','C1','C2','C3'],'D':['D0','D1','D2','D3']})
df_left
keyAB
0K0A0B0
1K1A1B1
2K2A2B2
3K4A3B3
df_right
keyCD
0K0C0D0
1K1C1D1
2K2C2D2
3K3C3D3

1. 内连接----共有键部分的连接

# 以key为主键,采用内连接的方式合并数据
result = pd.merge(df_left, df_right, on='key',how='inner')
result
keyABCD
0K0A0B0C0D0
1K1A1B1C1D1
2K2A2B2C2D2

图解过程如下:

  • 两个数据框df_left、df_right有相同的字段key
  • 默认是通过相同的字段(键)进行关联,取出键中相同的值(K0,K1,K2),若每个键的记录要全部显示
# 默认参数情况下的连接及为内连接
result = pd.merge(df_left,df_right)
result
keyABCD
0K0A0B0C0D0
1K1A1B1C1D1
2K2A2B2C2D2
# 也可以采用dataFrame对象的方法的方式调用
df_left.merge(df_right)
keyABCD
0K0A0B0C0D0
1K1A1B1C1D1
2K2A2B2C2D2

2. 左外连接----以左数据为主,保留左侧全部的连接

# 以key为主键,采用左外连接的方式合并数据
result = pd.merge(df_left, df_right, on='key', how='left')
result
keyABCD
0K0A0B0C0D0
1K1A1B1C1D1
2K2A2B2C2D2
3K4A3B3NaNNaN
# 类似的
result = df_left.merge(df_right,on='key',how='left')
result
keyABCD
0K0A0B0C0D0
1K1A1B1C1D1
2K2A2B2C2D2
3K4A3B3NaNNaN

图解过程如下:

  • 以左边数据框中的键(K0,K1,K2,K4)为基准;
  • 如果左边存在(K4)但是右边不存在(K4),则右边用NaN表示

3. 右外连接----以右数据为主,保留右侧全部的连接

# 以key为主键,采用右外连接的方式合并数据
result = pd.merge(df_left, df_right, on='key', how='right')
result
keyABCD
0K0A0B0C0D0
1K1A1B1C1D1
2K2A2B2C2D2
3K3NaNNaNC3D3

图解过程如下:

  • 以右边数据框中的键(K0,K1,K2,K3)为基准;
  • 如果右边存在(K3)但是右边不存在(K3),则左边用NaN表示

4. 全外连接----左右两侧数据都完全保留的连接

# 以key为主键,采用全外连接的方式合并数据
result = pd.merge(df_left, df_right, on='key', how='outer')
result
keyABCD
0K0A0B0C0D0
1K1A1B1C1D1
2K2A2B2C2D2
3K4A3B3NaNNaN
4K3NaNNaNC3D3

图解过程如下:
outer称之为外连接,在拼接的过程中会取两个数据框中键的并集进行拼接

  • 外连接,取出全部交集键的并集。例子中是user的并集
  • 如果某个键在某个数据框中不存在数据,则为NaN

5. 笛卡尔积----两个数据框中的数据交叉匹配,出现n1*n2的数据量

# 以key为主键,采用笛卡尔积连接的方式合并数据
result = pd.merge(df_left, df_right, how='cross')
print(result)
   key_x   A   B key_y   C   D
0     K0  A0  B0    K0  C0  D0
1     K0  A0  B0    K1  C1  D1
2     K0  A0  B0    K2  C2  D2
3     K0  A0  B0    K3  C3  D3
4     K1  A1  B1    K0  C0  D0
5     K1  A1  B1    K1  C1  D1
6     K1  A1  B1    K2  C2  D2
7     K1  A1  B1    K3  C3  D3
8     K2  A2  B2    K0  C0  D0
9     K2  A2  B2    K1  C1  D1
10    K2  A2  B2    K2  C2  D2
11    K2  A2  B2    K3  C3  D3
12    K4  A3  B3    K0  C0  D0
13    K4  A3  B3    K1  C1  D1
14    K4  A3  B3    K2  C2  D2
15    K4  A3  B3    K3  C3  D3

笛卡尔积的图解过程如下:

  • 出现的数据量是4*2,userid下面的数据交叉匹配
  • 在最终结果中相同的字段userid为了避免混淆,会带上默认的后缀_x、_y
6.1.2.2.2 pd.merge_ordered()

使用可选的填充/插值对有序数据执行合并。专为时间序列数据等有序数据而设计。

  • pd.merge_ordered()语法格式:
 pandas.merge_ordered(left, right, on=None, left_on=None, right_on=None, left_by=None, right_by=None, fill_method=None, suffixes=('_x', '_y'), how='outer')
  • 参数解释:

    • left: 用于连接的 左DataFrame

    • right: 用于连接的 右DataFrame

    • on: 连接关键字。必须 同时存在于 左DataFrame、右DataFrame

    • left_on: 左DataFrame 中用于连接的关键字

    • right_on: 右DataFrame 中用于连接的关键字

    • left_by: 对 左DataFrame 进行分组的关键字

    • right_by: 对 右DataFrame 进行分组的关键字

    • fill_method: 对缺失数据填充的值

    • suffixes: 连接后,同时存在于 左DataFrame、右DataFrame 中的字段,添加的后缀名

    • how: 连接方式。默认为 外连接

  • 注意:

    • 使用参数 on 时,不能同时使用 “left_on” 或 “right_on”

    • left_on 与 right_on 必须同时存在

    • 如果 on、left_on 、right_on 的参数值均为空时,默认以 同时存在于两个 DataFrame 中的列,为连接关键字。
      如果不存在共同列,将会报错:pandas.errors.MergeError: No common columns to perform merge on.

    • left_by 与 right_by 不能同时存在

pd.merge_ordered()实例:

  • 构建实例数据
df1 = pd.DataFrame({"key": ["a", "c", "e", "a", "c", "e"],"lvalue": [1, 2, 3, 1, 2, 3],"group": ["a", "a", "a", "b", "b", "b"]}
)df2 = pd.DataFrame({"key": ["b", "c", "d"], "rvalue": [1, 2, 3]})
df1
keylvaluegroup
0a1a
1c2a
2e3a
3a1b
4c2b
5e3b
df2 
keyrvalue
0b1
1c2
2d3
# df1                         df2
#   key    lvalue group           key  rvalue
# 0   a       1     a         0   b       1
# 1   c       2     a         1   c       2
# 2   e       3     a         2   d       3
# 3   a       1     b              
# 4   c       2     b              
# 5   e       3     b                    

1. 如果 left_by 与 right_by 均为空,等价于 merge

pd.merge_ordered(df1, df2).sort_values(by=["key", "lvalue"], ignore_index=True)
keylvaluegrouprvalue
0a1.0aNaN
1a1.0bNaN
2bNaNNaN1.0
3c2.0a2.0
4c2.0b2.0
5dNaNNaN3.0
6e3.0aNaN
7e3.0bNaN

等价于如下:

pd.merge(df1, df2, how="outer").sort_values(by=["key", "lvalue"], ignore_index=True) 
keylvaluegrouprvalue
0a1.0aNaN
1a1.0bNaN
2bNaNNaN1.0
3c2.0a2.0
4c2.0b2.0
5dNaNNaN3.0
6e3.0aNaN
7e3.0bNaN

2. 如果 left_by 或 right_by 不为空,会先按这个参数值对 DataFrame 进行分组,将分组后的 DataFrame 再进行连接

pd.merge_ordered(df1, df2, left_by="group")
#第一步:将 df1 根据 group 进行分组
# 第二步:将分组后的 df1 中每一组的数据,通过连接关键字 key 与 df2 进行连接 
keylvaluegrouprvalue
0a1.0aNaN
1bNaNa1.0
2c2.0a2.0
3dNaNa3.0
4e3.0aNaN
5a1.0bNaN
6bNaNb1.0
7c2.0b2.0
8dNaNb3.0
9e3.0bNaN
pd.merge_ordered(df1, df2, right_by="rvalue")
# 第一步:将 df2 根据 rvalue 进行分组
# 第二步:将分组后的 df2 中每一组的数据,通过连接关键字 key 与 df1 进行连接
keylvaluegrouprvalue
0a1.0a1
1a1.0b1
2bNaNNaN1
3c2.0a1
4c2.0b1
5e3.0a1
6e3.0b1
7a1.0a2
8a1.0b2
9c2.0a2
10c2.0b2
11e3.0a2
12e3.0b2
13a1.0a3
14a1.0b3
15c2.0a3
16c2.0b3
17dNaNNaN3
18e3.0a3
19e3.0b3

3. 如果,“left_by 或 right_by 的值” 与 “连接关键字” 相同,那无论是什么连接方式,结果都一样

pd.merge_ordered(df1, df2, left_by="key")
keylvaluegrouprvalue
0a1aNaN
1a1bNaN
2c2a2.0
3c2b2.0
4e3aNaN
5e3bNaN
pd.merge_ordered(df1, df2, left_by="key", how="inner") 
keylvaluegrouprvalue
0a1aNaN
1a1bNaN
2c2a2.0
3c2b2.0
4e3aNaN
5e3bNaN
pd.merge_ordered(df1, df2, left_by="key", how="right")
keylvaluegrouprvalue
0a1aNaN
1a1bNaN
2c2a2.0
3c2b2.0
4e3aNaN
5e3bNaN
6.1.2.2.3 pd.merge_asof()

pandas 的 merge_asof() 类似于有序的LEFT JOIN,只是我们在最近的键上匹配,而不是相等键。

  • pd.merge_asof()语法格式:
pandas.merge_asof(left,right,on=None, left_on=None, right_on=None, left_index=False, right_index=False, by=None, left_by=None, right_by=None, suffixes=(‘_x’, ‘_y’), tolerance=None, allow_exact_matches=True, direction=’backward’, )
  • 参数说明:

    • left, right: DataFrame
    • on:标签,要加入的字段名称。必须在两个DataFrame中都找到。
    • left_on:标签,要在左侧DataFrame中加入的字段名称。
    • right_on:标签,要在右侧DataFrame中加入的字段名称。
    • left_index:布尔值,使用左侧DataFrame的索引作为连接键。
    • right_index:布尔值,使用正确的DataFrame的索引作为连接键。
  • pd.merge_asof()实例:

# importing package 
import pandas # creating data 
left = pandas.DataFrame({'a':[1, 5, 10],  'left_val':['a', 'b', 'c']}) right = pandas.DataFrame({'a':[1, 2, 3, 6, 7], 'right_val':[1, 2, 3, 6, 7]}) # view data 
print(left) 
print(right) # applying merge_asof on data 
print(pandas.merge_asof(left, right, on='a')) 
print(pandas.merge_asof(left, right, on='a',allow_exact_matches=False))
    a left_val
0   1        a
1   5        b
2  10        ca  right_val
0  1          1
1  2          2
2  3          3
3  6          6
4  7          7a left_val  right_val
0   1        a          1
1   5        b          3
2  10        c          7a left_val  right_val
0   1        a        NaN
1   5        b        3.0
2  10        c        7.0
6.1.2.3 堆叠合并数据
  • dataframe.join(): 根据行索引连接多组数据
  • pd.concat(): 沿着某个轴方向堆叠多组数据
  • dataframe.append(): 向数据末尾追加若干行数据
6.1.2.3.0 构建数据
import pandas as pd
import numpy as npdf1 = pd.DataFrame({"姓名":["小明","小红","小周"],"年龄":[18,24,20]
})
df1
姓名年龄
0小明18
1小红24
2小周20
df2 = pd.DataFrame({"姓名":["小孙","小芳"],"年龄":[25,19]
})
df2
姓名年龄
0小孙25
1小芳19
df3 = pd.DataFrame({"地址":["深圳","广州","珠海"],"成绩":[600,630,598]
})
df3
地址成绩
0深圳600
1广州630
2珠海598
df4 = pd.DataFrame({"地址":["深圳","广州","东莞"],"爱好":["乒乓球","羽毛球","高尔夫"]
})
df4
地址爱好
0深圳乒乓球
1广州羽毛球
2东莞高尔夫
df5 = pd.DataFrame({"地址":["深圳","广州","东莞","上海","北京"],"爱好":["乒乓球","羽毛球","高尔夫","跑步","健身"]
})
df5
地址爱好
0深圳乒乓球
1广州羽毛球
2东莞高尔夫
3上海跑步
4北京健身
6.1.2.3.1 pd.concat()

解决两个表或者多个表按照纵向或者横向拼接。

  • pd.concat()的语法格式:
 pandas.concat(objs,  # 合并对象axis=0,   # 合并方向,默认是0纵轴方向join='outer', # 合并取的是交集inner还是并集outerignore_index=False, # 合并之后索引是否重新keys=None, # 在行索引的方向上带上原来数据的名字;主要是用于层次化索引,可以是任意的列表、数组、元组或者列表数组levels=None, # 指定用作层次化索引各级别上的索引,如果是设置了keysnames=None, # 行索引的名字,列表形式verify_integrity=False, # 检查行索引是否重复;有则报错sort=False, # 对非连接的轴进行排序copy=True   # 是否进行深拷贝)
  • pd.concat()的参数详细说明:

    • objs:Series,DataFrame或Panel对象的序列或映射。如果传递了dict,则排序的键将用作键参数,除非它被传递,在这种情况下,将选择值(见下文)。任何无对象将被静默删除,除非它们都是无,在这种情况下将引发一个ValueError。
    • axis:{0,1,…},默认为0。沿着连接的轴。
    • join:{‘inner’,‘outer’},默认为“outer”。如何处理其他轴上的索引。outer为联合和inner为交集。
    • ignore_index:boolean,default False。如果为True,请不要使用并置轴上的索引值。结果轴将被标记为0,…,n-1。如果要连接其中并置轴没有有意义的索引信息的对象,这将非常有用。注意,其他轴上的索引值在连接中仍然受到尊重。
    • join_axes:Index对象列表。用于其他n-1轴的特定索引,而不是执行内部/外部设置逻辑。
    • keys:序列,默认值无。使用传递的键作为最外层构建层次索引。如果为多索引,应该使用元组。
    • levels:序列列表,默认值无。用于构建MultiIndex的特定级别(唯一值)。否则,它们将从键推断。
    • names:list,default无。结果层次索引中的级别的名称。
    • verify_integrity:boolean,default False。检查新连接的轴是否包含重复项。这相对于实际的数据串联可能是非常昂贵的。
    • copy:boolean,default True。如果为False,请勿不必要地复制数据。
  • pd.concat()使用实例:

    • 根据实际数据调整合并的方向,默认是axis=0
    • 某个数据库中不存在的数据,用NaN代替
    • ignore_index是否保留原表索引,默认保留,为 True 会自动增加自然索引。
    • 指定取得交集inner还是并集outer,默认是并集outer

1. 默认情况是直接在纵向上进行合并

# 使用原索引
pd.concat([df1,df2])
姓名年龄
0小明18
1小红24
2小周20
0小孙25
1小芳19
# ignore_index=True,重新行索引
pd.concat([df1,df2],ignore_index=True)
姓名年龄
0小明18
1小红24
2小周20
3小孙25
4小芳19

2. axis指定轴方向上的合并,默认方向axis=0

pd.concat([df1,df2],axis=0)  #默认方向
姓名年龄
0小明18
1小红24
2小周20
0小孙25
1小芳19
pd.concat([df1,df3],axis=1) 
姓名年龄地址成绩
0小明18深圳600
1小红24广州630
2小周20珠海598
#缺失填充NaN
pd.concat([df1,df2],axis=1)
姓名年龄姓名年龄
0小明18小孙25.0
1小红24小芳19.0
2小周20NaNNaN

3. joni参数指定取得交集inner还是并集outer,默认是并集outer

pd.concat([df3,df4],join="outer")
#pd.concat([df3,df4])
地址成绩爱好
0深圳600.0NaN
1广州630.0NaN
2珠海598.0NaN
0深圳NaN乒乓球
1广州NaN羽毛球
2东莞NaN高尔夫
# df3和df4只有地址这个字段是相同的,所以保留了它,其他的舍弃:
pd.concat([df3,df4],join="inner")
地址
0深圳
1广州
2珠海
0深圳
1广州
2东莞

4. keys参数传递序列输入,默认值无。使用传递的键作为最外层构建层次索引。

  • 当我们设置了索引重排(ignore_index=True),keys参数就无效啦
pd.concat([df1,df2],keys=["df1","df2"])
姓名年龄
df10小明18
1小红24
2小周20
df20小孙25
1小芳19
#当我们设置了索引重排(ignore_index=True),keys参数就无效啦
pd.concat([df1,df2],keys=["df1","df2"],ignore_index=True)
姓名年龄
0小明18
1小红24
2小周20
3小孙25
4小芳19

5. name参数,指定每个层级索引名字

df6 = pd.concat([df1,df2],keys=["df1","df2"],names=["D1","D2"])
df6
姓名年龄
D1D2
df10小明18
1小红24
2小周20
df20小孙25
1小芳19

我们可以检查下df6的索引,发现是层级索引:

df6.index
MultiIndex([('df1', 0),('df1', 1),('df1', 2),('df2', 0),('df2', 1)],names=['D1', 'D2'])

6. 合并多个DataFrame

pd.concat([pd.concat([df1,df2],axis=0,ignore_index=True),df5],axis=1)
姓名年龄地址爱好
0小明18深圳乒乓球
1小红24广州羽毛球
2小周20东莞高尔夫
3小孙25上海跑步
4小芳19北京健身

等价于:分两步来实现:先合并df1、df2,将得到的结果和df5合并

df7 = pd.concat([df1,df2],axis=0,ignore_index=True)
df7
姓名年龄
0小明18
1小红24
2小周20
3小孙25
4小芳19
pd.concat([df7,df5],axis=1)
姓名年龄地址爱好
0小明18深圳乒乓球
1小红24广州羽毛球
2小周20东莞高尔夫
3小孙25上海跑步
4小芳19北京健身
6.1.2.3.2 dataframe.join()

dataframe内置的join方法是一种快速合并的方法。它默认以index作为对齐的列。

  • dataframe.join()的语法格式:
  dataframe.join(other,  # 待合并的另一个数据框on=None,  # 连接的键how='left',   # 连接方式:‘left’, ‘right’, ‘outer’, ‘inner’ 默认是leftlsuffix='',  # 左边(第一个)数据框相同键的后缀rsuffix='',  # 第二个数据框的键的后缀sort=False)  # 是否根据连接的键进行排序;默认False
  • dataframe.join()的参数说明:

    • other:DataFrame, Series, or list of DataFrame,另外一个dataframe, series,或者dataframe list。
    • on: 参与join的列,与sql中的on参数类似。
    • how: 连接方法,从{‘left’, ‘right’, ‘outer’, ‘inner’}中选取,默认’left’。
    • lsuffix: 左DataFrame中重复列的后缀
    • rsuffix: 右DataFrame中重复列的后缀
    • sort: 按字典序对结果在连接键上排序
  • join()的各种连接方法图示

  • dataframe.join()使用实例

模拟数据

df10 = pd.DataFrame({"name":["小红","小明","小孙","小周","小张"],"address":["深圳","广州","长沙","上海","苏州"]
})
df10
nameaddress
0小红深圳
1小明广州
2小孙长沙
3小周上海
4小张苏州
df11 = pd.DataFrame({"name":["小红","小明","小孙"],"sex":["女","男","男"],"age":[29,23,27]
})
df11
namesexage
0小红29
1小明23
2小孙27
df12 = pd.DataFrame({"name":["小红","小明"],"height":[173,177]
})
df12
nameheight
0小红173
1小明177
df13 = pd.DataFrame({"name":["小红","小明","小孙"],"sex":["女","男","男"],"score":[600,612,590]
})
df13
namesexscore
0小红600
1小明612
2小孙590

1. lsuffix、rsuffix参数,为了添加指定的后缀

df10.join(df11,lsuffix="_left",rsuffix="_right")
name_leftaddressname_rightsexage
0小红深圳小红29.0
1小明广州小明23.0
2小孙长沙小孙27.0
3小周上海NaNNaNNaN
4小张苏州NaNNaNNaN

2. how参数指定连接方法,默认是left,保留左边的全部字段,右边不存在的的数据用NaN

df10.join(df11,lsuffix="_left",rsuffix="_right",how="left")
name_leftaddressname_rightsexage
0小红深圳小红29.0
1小明广州小明23.0
2小孙长沙小孙27.0
3小周上海NaNNaNNaN
4小张苏州NaNNaNNaN
df10.join(df11,lsuffix="_left",rsuffix="_right",how="right")
name_leftaddressname_rightsexage
0小红深圳小红29
1小明广州小明23
2小孙长沙小孙27

3. on参数,指定参与join的列

可以在默认的参数结果中,name字段被分成了name_left和name_right,如何进行字段的合并呢???

  • 先把键当做行索引

  • 通过join合并

  • 通过reset_index()重新设置索引

# 1. 把键当作行索引
df10.set_index("name")
address
name
小红深圳
小明广州
小孙长沙
小周上海
小张苏州
df11.set_index("name")
sexage
name
小红29
小明23
小孙27
# 2.合并两个数据
df10.set_index("name").join(df11.set_index("name"))
addresssexage
name
小红深圳29.0
小明广州23.0
小孙长沙27.0
小周上海NaNNaN
小张苏州NaNNaN
# 3. 索引重置
df10.set_index("name").join(df11.set_index("name")).reset_index()
nameaddresssexage
0小红深圳29.0
1小明广州23.0
2小孙长沙27.0
3小周上海NaNNaN
4小张苏州NaNNaN

另外一种更为简便的方法:

df10.join(df11.set_index("name"),on="name")
nameaddresssexage
0小红深圳29.0
1小明广州23.0
2小孙长沙27.0
3小周上海NaNNaN
4小张苏州NaNNaN

4. 合并多个DataFrame

df10.set_index("name").join([df11.set_index("name"),df12.set_index("name"),]).reset_index()
nameaddresssexageheight
0小红深圳29.0173.0
1小明广州23.0177.0
2小孙长沙27.0NaN
3小周上海NaNNaNNaN
4小张苏州NaNNaNNaN

如果我们想要用merge函数来实现呢?

使用how=“outer”,保留全部字段的数据信息

pd.merge(pd.merge(df10,df11,how="outer"),df12,how="outer")
nameaddresssexageheight
0小红深圳29.0173.0
1小明广州23.0177.0
2小孙长沙27.0NaN
3小周上海NaNNaNNaN
4小张苏州NaNNaNNaN
6.1.2.3.3 dataframe.append()

向dataframe对象中添加新的行,如果添加的列名不在dataframe对象中,将会被当作新的列进行添加

  • dataframe.append()的语法格式:
DataFrame.append(other, ignore_index=False, verify_integrity=False, sort=False)
  • dataframe.append()的参数详细说明:

    • other:DataFrame、series、dict、list这样的数据结构
    • ignore_index:默认值为False,如果为True则不使用index标签
    • verify_integrity :默认值为False,如果为True当创建相同的index时会抛出ValueError的异常
    • sort:boolean,默认是None,该属性在pandas的0.23.0的版本才存在。
  • dataframe.append()的实例

模拟数据

df14= pd.DataFrame([[601,592],[23, 24]],columns=["小明","小红"])
df14
小明小红
0601592
12324
df15 = pd.DataFrame([["男","女"],["深圳","广州"]],columns=["小明","小红"])
df15
小明小红
0
1深圳广州

1. 添加Python字典

dict1 = {"小明":"乒乓球","小红":"排球"}
df14.append(dict1,ignore_index=True)
小明小红
0601592
12324
2乒乓球排球

若不指定ignore_index=True则会出错

2. 添加Series类型

s = pd.Series(dict1)
s
小明    乒乓球
小红     排球
dtype: object
df14.append(s,ignore_index=True)
小明小红
0601592
12324
2乒乓球排球

3. 添加DataFrame

df16 = pd.DataFrame(dict1,index=[0])
df16
小明小红
0乒乓球排球
df14.append(df16,ignore_index=True)
小明小红
0601592
12324
2乒乓球排球

4. 默认合并

df14.append(df15)
小明小红
0601592
12324
0
1深圳广州
#重新索引
df14.append(df15,ignore_index=True)
小明小红
0601592
12324
2
3深圳广州

5. verify_integrity参数
默认为False,为True,创建相同的index则会抛出异常的错误

df14.append(df15,verify_integrity=True)
---------------------------------------------------------------------------ValueError                                Traceback (most recent call last)<ipython-input-58-41bb9b875bb2> in <module>
----> 1 df14.append(df15,verify_integrity=True)D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\core\frame.py in append(self, other, ignore_index, verify_integrity, sort)8967                 ignore_index=ignore_index,8968                 verify_integrity=verify_integrity,
-> 8969                 sort=sort,8970             )8971         ).__finalize__(self, method="append")D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\util\_decorators.py in wrapper(*args, **kwargs)309                     stacklevel=stacklevel,310                 )
--> 311             return func(*args, **kwargs)312 313         return wrapperD:\ProgramFiles\Anaconda3\lib\site-packages\pandas\core\reshape\concat.py in concat(objs, axis, join, ignore_index, keys, levels, names, verify_integrity, sort, copy)302         verify_integrity=verify_integrity,303         copy=copy,
--> 304         sort=sort,305     )306 D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\core\reshape\concat.py in __init__(self, objs, axis, join, keys, levels, names, ignore_index, verify_integrity, copy, sort)477         self.copy = copy478 
--> 479         self.new_axes = self._get_new_axes()480 481     def get_result(self):D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\core\reshape\concat.py in _get_new_axes(self)549         return [550             self._get_concat_axis if i == self.bm_axis else self._get_comb_axis(i)
--> 551             for i in range(ndim)552         ]553 D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\core\reshape\concat.py in <listcomp>(.0)549         return [550             self._get_concat_axis if i == self.bm_axis else self._get_comb_axis(i)
--> 551             for i in range(ndim)552         ]553 D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\_libs\properties.pyx in pandas._libs.properties.CachedProperty.__get__()D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\core\reshape\concat.py in _get_concat_axis(self)609             )610 
--> 611         self._maybe_check_integrity(concat_axis)612 613         return concat_axisD:\ProgramFiles\Anaconda3\lib\site-packages\pandas\core\reshape\concat.py in _maybe_check_integrity(self, concat_index)617             if not concat_index.is_unique:618                 overlap = concat_index[concat_index.duplicated()].unique()
--> 619                 raise ValueError(f"Indexes have overlapping values: {overlap}")620 621 ValueError: Indexes have overlapping values: Int64Index([0, 1], dtype='int64')
df14.append(df15,verify_integrity=False)
小明小红
0601592
12324
0
1深圳广州
6.1.2.4 重叠合并数据

当两组数据的索引完全重合或部分重合,且数据中存在缺失值时,可以采用重叠合并的方式组合数据。重叠合并数据是一种并不常见的操作,它主要将一组数据的空值填充为另一组数据中对应位置的值。pandas中可使用combine_first()方法实现重叠合并数据的操作。

6.1.2.4.1 dfbine()

对两个DataFrame进行联合操作,实现合并的功能。
other参数传入被合并的DataFrame,
func参数传入合并的规则函数,两个参数都是必传参数。
func函数的入参是两个Series,分别来自两个DataFrame(将DataFrame按列遍历),返回结果是一个合并之后的Series,在函数中实现合并的规则。
func可以是匿名函数、Python库中定义好的函数、或自定义的函数,要满足两个入参一个返回值,且入参和返回值是数组或Series。如上面的例子中,使用了匿名函数,合并规则为返回两个DataFrame中非空数据更多的列。

  • 语法格式:
 dfbine(other: 'DataFrame',func,fill_value=None,overwrite: 'bool' = True,
) -> 'DataFrame'
  • 参数详细解释:

    • other:其他系列或要与调用者系列组合的列表类型
    • func:作为参数传递的函数,该函数将决定从哪个系列将元素放入该索引
    • fill_value:多索引时级别的整数值
    • overwrite:是否使用other中值填充df
  • dfbine()使用实例:

    0.构建数据框并定义函数

import pandas as pd 
import numpy as np
# 构建两个数据库
df1 = pd.DataFrame({'A': [11, 2, np.nan],'B': [4, np.nan, 6],'C': [7,np.nan,np.nan]},index=['one','two','three'])
df2 = pd.DataFrame({'A': [1, 12, 3], 'B': [np.nan,np.nan,6],'C': [7, 8, np.nan]}, index=['one','two','three'])# 定义匿名函数
take_smaller = lambda x, y: x if x.sum() < y.sum() else y# 定义函数
def take_bigger(x,y):if x.sum()>y.sum():print("x.sum:",x.sum())print("y.sum:",y.sum())print("bigger")print(x)return xelse:print("x.sum:",x.sum())print("y.sum:",y.sum())print("smaller")print(y)return y
df1
ABC
one11.04.07.0
two2.0NaNNaN
threeNaN6.0NaN
df2
ABC
one1NaN7.0
two12NaN8.0
three36.0NaN

1. func可以是匿名函数、标准函数或常规自定义函数

# 传递匿名函数
# 取列值和最小的列
# x:df1, y:df2
df1bine(df2, take_smaller, overwrite=False)  # df1 中不存在 C,返回 NaN
ABC
one11.0NaN7.0
two2.0NaNNaN
threeNaN6.0NaN
# 传递numpy标准函数
# 取各元素最小值
df1bine(df2,np.fmin,overwrite=False)
ABC
one1.04.07.0
two2.0NaN8.0
three3.06.0NaN
# 传递numpy标准函数
# 取各元素最大值
df1bine(df2,np.fmax,overwrite=False)
ABC
one11.04.07.0
two12.0NaN8.0
three3.06.0NaN
# 传递常规自定义函数
# 取列值和最大的列
# x:df1, y:df2
df1bine(df2,take_bigger,overwrite=False)
x.sum: 13.0
y.sum: 16.0
smaller
one       1.0
two      12.0
three     3.0
Name: A, dtype: float64
x.sum: 10.0
y.sum: 6.0
bigger
one      4.0
two      NaN
three    6.0
Name: B, dtype: float64
x.sum: 7.0
y.sum: 15.0
smaller
one      7.0
two      8.0
three    NaN
Name: C, dtype: float64
ABC
one1.04.07.0
two12.0NaN8.0
three3.06.0NaN

2. 合并时填充空值
fill_value: 先用fill_value填充DataFrame中的空值,再按传入的函数进行合并操作。
fill_value会填充DataFrame中所有列的空值,而且是在合并之前先填充。

# 构建dataframe
df3 = pd.DataFrame({'A':[1,2,np.nan],'B':[4,np.nan,16],'C':[7,np.nan,np.nan]},index=['one','two','three'])
df3 
ABC
one1.04.07.0
two2.0NaNNaN
threeNaN16.0NaN
df4 = pd.DataFrame({'A':[11,2,3],'B':[np.nan,np.nan,6],'D':[10,np.nan,12]},index=['one','two','three'])
df4
ABD
one11NaN10.0
two2NaNNaN
three36.012.0
# 定义保留最大值函数
def save_max(s1,s2):s = s1for ind in s1.index:if ind in s2.index and s1[ind] < s2[ind]:s[ind] = s2[ind]return s 
df3bine(df4, save_max, fill_value=5)
ABCD
one11.05.07.010.0
two2.05.05.05.0
three5.016.05.012.0

上面的例子中自定义了函数save_max(),合并时取同位置的最大值,原理如下图。

3. 不处理缺失的列

df3bine(df4,save_max,fill_value=5,overwrite=False)
ABCD
one11.05.07.010.0
two2.05.0NaN5.0
three5.016.0NaN12.0

overwrite: 如果调用combine()方法的DataFrame中存在的列,在传入combine()方法的DataFrame中不存在,则先在传入的DataFrame中添加一列空值。overwrite参数默认为True.上一例子中,其填充原理如下:

如果将overwrite参数设置成False,则不会给传入combine()方法的DataFrame添加不存在的列,并且合并时不会处理调用combine()方法的DataFrame中多出的列,多出的列直接原样返回。原理如下图。

再举一个栗子

df5 = pd.DataFrame({'A': [1, 2], 'B': [4, 5]})
df6 = pd.DataFrame({'B': [8, 6], 'C': [1, 7], }, index=[1, 2])
df5,df6
(   A  B0  1  41  2  5,B  C1  8  12  6  7)
df5bine(df6,save_max,overwrite=True,fill_value=3)
ABC
03.04.03.0
13.08.03.0
23.06.07.0

处理过程如下图:

df5bine(df6,save_max,overwrite=False,fill_value=3)
ABC
01.04.03.0
12.08.03.0
2NaN6.07.0

处理过程如下图:

6.1.2.4.2 dfbine_first()

对两个DataFrame进行联合操作,实现合并的功能,other参数传入被合并的DataFrame。

combine_first()方法根据DataFrame的行索引和列索引,对比两个DataFrame中相同位置的数据,优先取非空的数据进行合并。

如果调用combine_first()方法的df1中数据非空,则结果保留df1中的数据;
如果df1中的数据为空值且传入combine_first()方法的df2中数据非空,则结果取df2中的数据;
如果df1和df2中的数据都为空值,则结果保留df1中的空值(空值有三种: np.nan、None 和 pd.NaT)。

即使两个DataFrame的形状不相同也不受影响,联合时主要是根据索引来定位数据的位置。

df1,df2
(          A    B    Cone    11.0  4.0  7.0two     2.0  NaN  NaNthree   NaN  6.0  NaN,A    B    Cone     1  NaN  7.0two    12  NaN  8.0three   3  6.0  NaN)
df1bine_first(df2)
ABC
one11.04.07.0
two2.0NaN8.0
three3.06.0NaN
df2bine_first(df1)
ABC
one1.04.07.0
two12.0NaN8.0
three3.06.0NaN

6.1.2.5 数据合并应用案例

xsjc.xlxs 表中有3个表单:student,coursestudent_course,分别记录了学生信息、课程信息与选课信息。如下:

现在我们通过合并函数将3个sheet中的内容关联起来

6.1.2.5.1 读取数据并查看基本信息
import pandas as pd 
import numpy as np df_student = pd.read_excel("xscj.xlsx",sheet_name="student")
df_course = pd.read_excel("xscj.xlsx",sheet_name="course")
df_stuCourse = pd.read_excel("xscj.xlsx",sheet_name=2)
# 查看前5行
df_student.head()
学号姓名专业性别出生年月总学分备注
081101刘华通信工程11991-03-0858NaN
181102程明计算机11991-02-0158NaN
281103王燕计算机01989-10-0658NaN
381104韦严平计算机11990-08-2658NaN
481106李方方计算机11990-11-2058NaN
# 查看前5行
df_course.head()
课程号课程名开课学期学时学分
0101计算机基础1805
1102程序设计与语言2684
2206离散数学4684
3208数据结构5684
4209操作系统6684
# 查看前5行
df_stuCourse.head()
学号课程号成绩
08110110180
18110110278
28110120676
38110210278
48110220678
#查看数据总体信息
df_student.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 23 entries, 0 to 22
Data columns (total 7 columns):#   Column  Non-Null Count  Dtype         
---  ------  --------------  -----         0   学号      23 non-null     int64         1   姓名      23 non-null     object        2   专业      23 non-null     object        3   性别      23 non-null     int64         4   出生年月    23 non-null     datetime64[ns]5   总学分     23 non-null     int64         6   备注      7 non-null      object        
dtypes: datetime64[ns](1), int64(3), object(3)
memory usage: 1.4+ KB
#查看数据总体信息
df_course.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 9 entries, 0 to 8
Data columns (total 5 columns):#   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 0   课程号     9 non-null      int64 1   课程名     9 non-null      object2   开课学期    9 non-null      int64 3   学时      9 non-null      int64 4   学分      9 non-null      int64 
dtypes: int64(4), object(1)
memory usage: 488.0+ bytes
#查看数据总体信息
df_stuCourse.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 41 entries, 0 to 40
Data columns (total 3 columns):#   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 0   学号      41 non-null     int64 1   课程号     41 non-null     int64 2   成绩      41 non-null     object
dtypes: int64(2), object(1)
memory usage: 1.1+ KB

注意查看上面信息,成绩本应为数值,这里是object,应该是有非数存在
用**pd.to_numeric()**转换成数字,可见其31行是字符“作弊”

6.1.2.5.2 处理缺失值
pd.to_numeric(df_stuCourse['成绩'])
---------------------------------------------------------------------------ValueError                                Traceback (most recent call last)D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\_libs\lib.pyx in pandas._libs.lib.maybe_convert_numeric()ValueError: Unable to parse string "作弊"During handling of the above exception, another exception occurred:ValueError                                Traceback (most recent call last)<ipython-input-91-a53b09b91987> in <module>
----> 1 pd.to_numeric(df_stuCourse['成绩'])D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\core\tools\numeric.py in to_numeric(arg, errors, downcast)182         try:183             values, _ = lib.maybe_convert_numeric(
--> 184                 values, set(), coerce_numeric=coerce_numeric185             )186         except (ValueError, TypeError):D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\_libs\lib.pyx in pandas._libs.lib.maybe_convert_numeric()ValueError: Unable to parse string "作弊" at position 31
df_stuCourse["成绩"][31]
'作弊'
# 采用errors="coerce"强制转换
df_stuCourse['成绩']=pd.to_numeric(df_stuCourse['成绩'],errors='coerce')
df_stuCourse.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 41 entries, 0 to 40
Data columns (total 3 columns):#   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  0   学号      41 non-null     int64  1   课程号     41 non-null     int64  2   成绩      40 non-null     float64
dtypes: float64(1), int64(2)
memory usage: 1.1 KB

可以看到,"成绩"有一个缺失值,是"作弊"所致。

df_stuCourse["成绩"][31]
nan
# "作弊"给0分
df_stuCourse=df_stuCourse.fillna(0)
df_stuCourse["成绩"][31]
0.0
6.1.2.5.3 合并"student”表与“student_course"表
df_student_stuCourse = pd.merge(df_student,df_stuCourse,how="outer")
df_student_stuCourse
学号姓名专业性别出生年月总学分备注课程号成绩
081101刘华通信工程11991-03-0858NaN101.080.0
181101刘华通信工程11991-03-0858NaN102.078.0
281101刘华通信工程11991-03-0858NaN206.076.0
381102程明计算机11991-02-0158NaN102.078.0
481102程明计算机11991-02-0158NaN206.078.0
581103王燕计算机01989-10-0658NaN101.052.0
681103王燕计算机01989-10-0658NaN102.070.0
781103王燕计算机01989-10-0658NaN206.081.0
881104韦严平计算机11990-08-2658NaN101.090.0
981104韦严平计算机11990-08-2658NaN102.084.0
1081104韦严平计算机11990-08-2658NaN206.065.0
1181106李方方计算机11990-11-2058NaN101.059.0
1281106李方方计算机11990-11-2058NaN102.071.0
1381106李方方计算机11990-11-2058NaN206.081.0
1481107李明计算机11990-05-0162提前修完《数据结构》,并获学分101.078.0
1581107李明计算机11990-05-0162提前修完《数据结构》,并获学分102.080.0
1681107李明计算机11990-05-0162提前修完《数据结构》,并获学分206.068.0
1781108林一帆计算机11989-08-0560已提前修完一门课101.085.0
1881108林一帆计算机11989-08-0560已提前修完一门课102.055.0
1981108林一帆计算机11989-08-0560已提前修完一门课206.087.0
2081109张强民计算机11989-08-1158NaN101.066.0
2181109张强民计算机11989-08-1158NaN102.083.0
2281109张强民计算机11989-08-1158NaN206.070.0
2381110张蔚计算机01991-07-2258三好生101.095.0
2481110张蔚计算机01991-07-2258三好生102.090.0
2581110张蔚计算机01991-07-2258三好生206.089.0
2681111赵琳计算机01990-03-1858NaN101.091.0
2781111赵琳计算机01990-03-1858NaN102.070.0
2881111赵琳计算机01990-03-1858NaN206.076.0
2981113严红计算机01989-08-1156有一门功课不及格,待补考101.063.0
3081113严红计算机01989-08-1156有一门功课不及格,待补考102.079.0
3181113严红计算机01989-08-1156有一门功课不及格,待补考206.00.0
3281201王敏通信工程11989-06-1042NaN101.080.0
3381202王林通信工程11989-01-2940有一门课不及格,待补考101.058.0
3481203王玉民通信工程11990-03-2652NaN101.087.0
3581204马琳琳通信工程01989-02-1052NaN101.091.0
3681206李计通信工程11989-09-2052NaNNaNNaN
3781210李红庆通信工程11989-05-0154已提前修完一门课,并获得学分101.076.0
3881216孙祥欣通信工程11989-03-0952NaN101.081.0
3981218孙研通信工程11990-10-0952NaN101.070.0
4081220吴薇华通信工程01990-03-1852NaN101.082.0
4181221刘燕敏通信工程01989-11-1252NaN101.076.0
4281251罗林琳通信工程01990-01-3060转专业学习NaNNaN
4381255李牧计算机11990-10-1458NaNNaNNaN

采用outer方式连接,考虑考虑课程号为"NaN"的意义???
课程号为"NaN"意味着该生没有选课,选课表中无记录。

请找出没有选修课程的学生

df_student_stuCourse[["学号",'姓名',"专业"]][df_student_stuCourse['课程号'].isna()]
学号姓名专业
3681206李计通信工程
4281251罗林琳通信工程
4381255李牧计算机

也可以采用右连接方式

# 采用"right"方式连接
df_student_stuCourse2 = pd.merge(df_student,df_stuCourse,how="right")
df_student_stuCourse2
学号姓名专业性别出生年月总学分备注课程号成绩
081101刘华通信工程11991-03-0858NaN10180.0
181101刘华通信工程11991-03-0858NaN10278.0
281101刘华通信工程11991-03-0858NaN20676.0
381102程明计算机11991-02-0158NaN10278.0
481102程明计算机11991-02-0158NaN20678.0
581103王燕计算机01989-10-0658NaN10152.0
681103王燕计算机01989-10-0658NaN10270.0
781103王燕计算机01989-10-0658NaN20681.0
881104韦严平计算机11990-08-2658NaN10190.0
981104韦严平计算机11990-08-2658NaN10284.0
1081104韦严平计算机11990-08-2658NaN20665.0
1181106李方方计算机11990-11-2058NaN10159.0
1281106李方方计算机11990-11-2058NaN10271.0
1381106李方方计算机11990-11-2058NaN20681.0
1481107李明计算机11990-05-0162提前修完《数据结构》,并获学分10178.0
1581107李明计算机11990-05-0162提前修完《数据结构》,并获学分10280.0
1681107李明计算机11990-05-0162提前修完《数据结构》,并获学分20668.0
1781108林一帆计算机11989-08-0560已提前修完一门课10185.0
1881108林一帆计算机11989-08-0560已提前修完一门课10255.0
1981108林一帆计算机11989-08-0560已提前修完一门课20687.0
2081109张强民计算机11989-08-1158NaN10166.0
2181109张强民计算机11989-08-1158NaN10283.0
2281109张强民计算机11989-08-1158NaN20670.0
2381110张蔚计算机01991-07-2258三好生10195.0
2481110张蔚计算机01991-07-2258三好生10290.0
2581110张蔚计算机01991-07-2258三好生20689.0
2681111赵琳计算机01990-03-1858NaN10191.0
2781111赵琳计算机01990-03-1858NaN10270.0
2881111赵琳计算机01990-03-1858NaN20676.0
2981113严红计算机01989-08-1156有一门功课不及格,待补考10163.0
3081113严红计算机01989-08-1156有一门功课不及格,待补考10279.0
3181113严红计算机01989-08-1156有一门功课不及格,待补考2060.0
3281201王敏通信工程11989-06-1042NaN10180.0
3381202王林通信工程11989-01-2940有一门课不及格,待补考10158.0
3481203王玉民通信工程11990-03-2652NaN10187.0
3581204马琳琳通信工程01989-02-1052NaN10191.0
3681210李红庆通信工程11989-05-0154已提前修完一门课,并获得学分10176.0
3781216孙祥欣通信工程11989-03-0952NaN10181.0
3881218孙研通信工程11990-10-0952NaN10170.0
3981220吴薇华通信工程01990-03-1852NaN10182.0
4081221刘燕敏通信工程01989-11-1252NaN10176.0
6.1.2.5.4 合并"student”表与“student_course"表合并的结果与“course”表
df_student_stuCourse.join(df_course.set_index("课程号"),on="课程号")
学号姓名专业性别出生年月总学分备注课程号成绩课程名开课学期学时学分
081101刘华通信工程11991-03-0858NaN101.080.0计算机基础1.080.05.0
181101刘华通信工程11991-03-0858NaN102.078.0程序设计与语言2.068.04.0
281101刘华通信工程11991-03-0858NaN206.076.0离散数学4.068.04.0
381102程明计算机11991-02-0158NaN102.078.0程序设计与语言2.068.04.0
481102程明计算机11991-02-0158NaN206.078.0离散数学4.068.04.0
581103王燕计算机01989-10-0658NaN101.052.0计算机基础1.080.05.0
681103王燕计算机01989-10-0658NaN102.070.0程序设计与语言2.068.04.0
781103王燕计算机01989-10-0658NaN206.081.0离散数学4.068.04.0
881104韦严平计算机11990-08-2658NaN101.090.0计算机基础1.080.05.0
981104韦严平计算机11990-08-2658NaN102.084.0程序设计与语言2.068.04.0
1081104韦严平计算机11990-08-2658NaN206.065.0离散数学4.068.04.0
1181106李方方计算机11990-11-2058NaN101.059.0计算机基础1.080.05.0
1281106李方方计算机11990-11-2058NaN102.071.0程序设计与语言2.068.04.0
1381106李方方计算机11990-11-2058NaN206.081.0离散数学4.068.04.0
1481107李明计算机11990-05-0162提前修完《数据结构》,并获学分101.078.0计算机基础1.080.05.0
1581107李明计算机11990-05-0162提前修完《数据结构》,并获学分102.080.0程序设计与语言2.068.04.0
1681107李明计算机11990-05-0162提前修完《数据结构》,并获学分206.068.0离散数学4.068.04.0
1781108林一帆计算机11989-08-0560已提前修完一门课101.085.0计算机基础1.080.05.0
1881108林一帆计算机11989-08-0560已提前修完一门课102.055.0程序设计与语言2.068.04.0
1981108林一帆计算机11989-08-0560已提前修完一门课206.087.0离散数学4.068.04.0
2081109张强民计算机11989-08-1158NaN101.066.0计算机基础1.080.05.0
2181109张强民计算机11989-08-1158NaN102.083.0程序设计与语言2.068.04.0
2281109张强民计算机11989-08-1158NaN206.070.0离散数学4.068.04.0
2381110张蔚计算机01991-07-2258三好生101.095.0计算机基础1.080.05.0
2481110张蔚计算机01991-07-2258三好生102.090.0程序设计与语言2.068.04.0
2581110张蔚计算机01991-07-2258三好生206.089.0离散数学4.068.04.0
2681111赵琳计算机01990-03-1858NaN101.091.0计算机基础1.080.05.0
2781111赵琳计算机01990-03-1858NaN102.070.0程序设计与语言2.068.04.0
2881111赵琳计算机01990-03-1858NaN206.076.0离散数学4.068.04.0
2981113严红计算机01989-08-1156有一门功课不及格,待补考101.063.0计算机基础1.080.05.0
3081113严红计算机01989-08-1156有一门功课不及格,待补考102.079.0程序设计与语言2.068.04.0
3181113严红计算机01989-08-1156有一门功课不及格,待补考206.00.0离散数学4.068.04.0
3281201王敏通信工程11989-06-1042NaN101.080.0计算机基础1.080.05.0
3381202王林通信工程11989-01-2940有一门课不及格,待补考101.058.0计算机基础1.080.05.0
3481203王玉民通信工程11990-03-2652NaN101.087.0计算机基础1.080.05.0
3581204马琳琳通信工程01989-02-1052NaN101.091.0计算机基础1.080.05.0
3681206李计通信工程11989-09-2052NaNNaNNaNNaNNaNNaNNaN
3781210李红庆通信工程11989-05-0154已提前修完一门课,并获得学分101.076.0计算机基础1.080.05.0
3881216孙祥欣通信工程11989-03-0952NaN101.081.0计算机基础1.080.05.0
3981218孙研通信工程11990-10-0952NaN101.070.0计算机基础1.080.05.0
4081220吴薇华通信工程01990-03-1852NaN101.082.0计算机基础1.080.05.0
4181221刘燕敏通信工程01989-11-1252NaN101.076.0计算机基础1.080.05.0
4281251罗林琳通信工程01990-01-3060转专业学习NaNNaNNaNNaNNaNNaN
4381255李牧计算机11990-10-1458NaNNaNNaNNaNNaNNaNNaN
df_student_stuCourse2.join(df_course.set_index("课程号"),on="课程号")
学号姓名专业性别出生年月总学分备注课程号成绩课程名开课学期学时学分
081101刘华通信工程11991-03-0858NaN10180.0计算机基础1805
181101刘华通信工程11991-03-0858NaN10278.0程序设计与语言2684
281101刘华通信工程11991-03-0858NaN20676.0离散数学4684
381102程明计算机11991-02-0158NaN10278.0程序设计与语言2684
481102程明计算机11991-02-0158NaN20678.0离散数学4684
581103王燕计算机01989-10-0658NaN10152.0计算机基础1805
681103王燕计算机01989-10-0658NaN10270.0程序设计与语言2684
781103王燕计算机01989-10-0658NaN20681.0离散数学4684
881104韦严平计算机11990-08-2658NaN10190.0计算机基础1805
981104韦严平计算机11990-08-2658NaN10284.0程序设计与语言2684
1081104韦严平计算机11990-08-2658NaN20665.0离散数学4684
1181106李方方计算机11990-11-2058NaN10159.0计算机基础1805
1281106李方方计算机11990-11-2058NaN10271.0程序设计与语言2684
1381106李方方计算机11990-11-2058NaN20681.0离散数学4684
1481107李明计算机11990-05-0162提前修完《数据结构》,并获学分10178.0计算机基础1805
1581107李明计算机11990-05-0162提前修完《数据结构》,并获学分10280.0程序设计与语言2684
1681107李明计算机11990-05-0162提前修完《数据结构》,并获学分20668.0离散数学4684
1781108林一帆计算机11989-08-0560已提前修完一门课10185.0计算机基础1805
1881108林一帆计算机11989-08-0560已提前修完一门课10255.0程序设计与语言2684
1981108林一帆计算机11989-08-0560已提前修完一门课20687.0离散数学4684
2081109张强民计算机11989-08-1158NaN10166.0计算机基础1805
2181109张强民计算机11989-08-1158NaN10283.0程序设计与语言2684
2281109张强民计算机11989-08-1158NaN20670.0离散数学4684
2381110张蔚计算机01991-07-2258三好生10195.0计算机基础1805
2481110张蔚计算机01991-07-2258三好生10290.0程序设计与语言2684
2581110张蔚计算机01991-07-2258三好生20689.0离散数学4684
2681111赵琳计算机01990-03-1858NaN10191.0计算机基础1805
2781111赵琳计算机01990-03-1858NaN10270.0程序设计与语言2684
2881111赵琳计算机01990-03-1858NaN20676.0离散数学4684
2981113严红计算机01989-08-1156有一门功课不及格,待补考10163.0计算机基础1805
3081113严红计算机01989-08-1156有一门功课不及格,待补考10279.0程序设计与语言2684
3181113严红计算机01989-08-1156有一门功课不及格,待补考2060.0离散数学4684
3281201王敏通信工程11989-06-1042NaN10180.0计算机基础1805
3381202王林通信工程11989-01-2940有一门课不及格,待补考10158.0计算机基础1805
3481203王玉民通信工程11990-03-2652NaN10187.0计算机基础1805
3581204马琳琳通信工程01989-02-1052NaN10191.0计算机基础1805
3681210李红庆通信工程11989-05-0154已提前修完一门课,并获得学分10176.0计算机基础1805
3781216孙祥欣通信工程11989-03-0952NaN10181.0计算机基础1805
3881218孙研通信工程11990-10-0952NaN10170.0计算机基础1805
3981220吴薇华通信工程01990-03-1852NaN10182.0计算机基础1805
4081221刘燕敏通信工程01989-11-1252NaN10176.0计算机基础1805

一次性连接多表

df_student.join(df_stuCourse.set_index("学号"),on="学号").join(df_course.set_index("课程号"),on="课程号").reset_index()
index学号姓名专业性别出生年月总学分备注课程号成绩课程名开课学期学时学分
0081101刘华通信工程11991-03-0858NaN101.080.0计算机基础1.080.05.0
1081101刘华通信工程11991-03-0858NaN102.078.0程序设计与语言2.068.04.0
2081101刘华通信工程11991-03-0858NaN206.076.0离散数学4.068.04.0
3181102程明计算机11991-02-0158NaN102.078.0程序设计与语言2.068.04.0
4181102程明计算机11991-02-0158NaN206.078.0离散数学4.068.04.0
5281103王燕计算机01989-10-0658NaN101.052.0计算机基础1.080.05.0
6281103王燕计算机01989-10-0658NaN102.070.0程序设计与语言2.068.04.0
7281103王燕计算机01989-10-0658NaN206.081.0离散数学4.068.04.0
8381104韦严平计算机11990-08-2658NaN101.090.0计算机基础1.080.05.0
9381104韦严平计算机11990-08-2658NaN102.084.0程序设计与语言2.068.04.0
10381104韦严平计算机11990-08-2658NaN206.065.0离散数学4.068.04.0
11481106李方方计算机11990-11-2058NaN101.059.0计算机基础1.080.05.0
12481106李方方计算机11990-11-2058NaN102.071.0程序设计与语言2.068.04.0
13481106李方方计算机11990-11-2058NaN206.081.0离散数学4.068.04.0
14581107李明计算机11990-05-0162提前修完《数据结构》,并获学分101.078.0计算机基础1.080.05.0
15581107李明计算机11990-05-0162提前修完《数据结构》,并获学分102.080.0程序设计与语言2.068.04.0
16581107李明计算机11990-05-0162提前修完《数据结构》,并获学分206.068.0离散数学4.068.04.0
17681108林一帆计算机11989-08-0560已提前修完一门课101.085.0计算机基础1.080.05.0
18681108林一帆计算机11989-08-0560已提前修完一门课102.055.0程序设计与语言2.068.04.0
19681108林一帆计算机11989-08-0560已提前修完一门课206.087.0离散数学4.068.04.0
20781109张强民计算机11989-08-1158NaN101.066.0计算机基础1.080.05.0
21781109张强民计算机11989-08-1158NaN102.083.0程序设计与语言2.068.04.0
22781109张强民计算机11989-08-1158NaN206.070.0离散数学4.068.04.0
23881110张蔚计算机01991-07-2258三好生101.095.0计算机基础1.080.05.0
24881110张蔚计算机01991-07-2258三好生102.090.0程序设计与语言2.068.04.0
25881110张蔚计算机01991-07-2258三好生206.089.0离散数学4.068.04.0
26981111赵琳计算机01990-03-1858NaN101.091.0计算机基础1.080.05.0
27981111赵琳计算机01990-03-1858NaN102.070.0程序设计与语言2.068.04.0
28981111赵琳计算机01990-03-1858NaN206.076.0离散数学4.068.04.0
291081113严红计算机01989-08-1156有一门功课不及格,待补考101.063.0计算机基础1.080.05.0
301081113严红计算机01989-08-1156有一门功课不及格,待补考102.079.0程序设计与语言2.068.04.0
311081113严红计算机01989-08-1156有一门功课不及格,待补考206.00.0离散数学4.068.04.0
321181201王敏通信工程11989-06-1042NaN101.080.0计算机基础1.080.05.0
331281202王林通信工程11989-01-2940有一门课不及格,待补考101.058.0计算机基础1.080.05.0
341381203王玉民通信工程11990-03-2652NaN101.087.0计算机基础1.080.05.0
351481204马琳琳通信工程01989-02-1052NaN101.091.0计算机基础1.080.05.0
361581206李计通信工程11989-09-2052NaNNaNNaNNaNNaNNaNNaN
371681210李红庆通信工程11989-05-0154已提前修完一门课,并获得学分101.076.0计算机基础1.080.05.0
381781216孙祥欣通信工程11989-03-0952NaN101.081.0计算机基础1.080.05.0
391881218孙研通信工程11990-10-0952NaN101.070.0计算机基础1.080.05.0
401981220吴薇华通信工程01990-03-1852NaN101.082.0计算机基础1.080.05.0
412081221刘燕敏通信工程01989-11-1252NaN101.076.0计算机基础1.080.05.0
422181251罗林琳通信工程01990-01-3060转专业学习NaNNaNNaNNaNNaNNaN
432281255李牧计算机11990-10-1458NaNNaNNaNNaNNaNNaNNaN
df_student.join(df_stuCourse.set_index("学号"),on="学号",how="inner").join(df_course.set_index("课程号"),on="课程号").reset_index()
index学号姓名专业性别出生年月总学分备注课程号成绩课程名开课学期学时学分
0081101刘华通信工程11991-03-0858NaN10180.0计算机基础1805
1081101刘华通信工程11991-03-0858NaN10278.0程序设计与语言2684
2081101刘华通信工程11991-03-0858NaN20676.0离散数学4684
3181102程明计算机11991-02-0158NaN10278.0程序设计与语言2684
4181102程明计算机11991-02-0158NaN20678.0离散数学4684
5281103王燕计算机01989-10-0658NaN10152.0计算机基础1805
6281103王燕计算机01989-10-0658NaN10270.0程序设计与语言2684
7281103王燕计算机01989-10-0658NaN20681.0离散数学4684
8381104韦严平计算机11990-08-2658NaN10190.0计算机基础1805
9381104韦严平计算机11990-08-2658NaN10284.0程序设计与语言2684
10381104韦严平计算机11990-08-2658NaN20665.0离散数学4684
11481106李方方计算机11990-11-2058NaN10159.0计算机基础1805
12481106李方方计算机11990-11-2058NaN10271.0程序设计与语言2684
13481106李方方计算机11990-11-2058NaN20681.0离散数学4684
14581107李明计算机11990-05-0162提前修完《数据结构》,并获学分10178.0计算机基础1805
15581107李明计算机11990-05-0162提前修完《数据结构》,并获学分10280.0程序设计与语言2684
16581107李明计算机11990-05-0162提前修完《数据结构》,并获学分20668.0离散数学4684
17681108林一帆计算机11989-08-0560已提前修完一门课10185.0计算机基础1805
18681108林一帆计算机11989-08-0560已提前修完一门课10255.0程序设计与语言2684
19681108林一帆计算机11989-08-0560已提前修完一门课20687.0离散数学4684
20781109张强民计算机11989-08-1158NaN10166.0计算机基础1805
21781109张强民计算机11989-08-1158NaN10283.0程序设计与语言2684
22781109张强民计算机11989-08-1158NaN20670.0离散数学4684
23881110张蔚计算机01991-07-2258三好生10195.0计算机基础1805
24881110张蔚计算机01991-07-2258三好生10290.0程序设计与语言2684
25881110张蔚计算机01991-07-2258三好生20689.0离散数学4684
26981111赵琳计算机01990-03-1858NaN10191.0计算机基础1805
27981111赵琳计算机01990-03-1858NaN10270.0程序设计与语言2684
28981111赵琳计算机01990-03-1858NaN20676.0离散数学4684
291081113严红计算机01989-08-1156有一门功课不及格,待补考10163.0计算机基础1805
301081113严红计算机01989-08-1156有一门功课不及格,待补考10279.0程序设计与语言2684
311081113严红计算机01989-08-1156有一门功课不及格,待补考2060.0离散数学4684
321181201王敏通信工程11989-06-1042NaN10180.0计算机基础1805
331281202王林通信工程11989-01-2940有一门课不及格,待补考10158.0计算机基础1805
341381203王玉民通信工程11990-03-2652NaN10187.0计算机基础1805
351481204马琳琳通信工程01989-02-1052NaN10191.0计算机基础1805
361681210李红庆通信工程11989-05-0154已提前修完一门课,并获得学分10176.0计算机基础1805
371781216孙祥欣通信工程11989-03-0952NaN10181.0计算机基础1805
381881218孙研通信工程11990-10-0952NaN10170.0计算机基础1805
391981220吴薇华通信工程01990-03-1852NaN10182.0计算机基础1805
402081221刘燕敏通信工程01989-11-1252NaN10176.0计算机基础1805

6.2 数据变换

6.2.1 数据变换概述

在对数据进行分析或挖掘之前,数据必须满足一定的条件,比如方差分析时要求数据具有正态性、方差齐性、独立性、无偏性,需进行诸如平方根、对数、平方根反正弦操作,实现从一种形式到另一种“适当”形式的变换,以适用于分析或挖掘的需求,这一过程就是数据变换。

数据变换主要是从数据中找到特征表示,通过一些转换方法减少有效变量的数目或找到数据的不变式,常见的操作可以分为数据标准化处理、数据离散化处理和数据泛化处理三类。

6.2.1.1 数据标准化处理

数据标准化处理是将数据按照一定的比例缩放,使之投射到一个比较小的特定区间
常用的数据标准化处理有:最小-最大标准化均值标准化(Z-Score)小数定标标准化

  • 小数定标标准化

通过移动小数点的位置来进行规范化。小数点移动的位数取决于该属性数据取值的最大绝对值。

例如:属性A的取值范围是-800到70,那么就可以将数据的小数点整体向左移三位即[-0.8,0.07]

利用numpy对数据进行小数定标规范化的方法如下:

    j = np.ceil(np.log10(np.max(abs(x))))scaled_x = x/(10**j)
6.2.1.2 数据离散化处理

数据离散化处理一般是在数据的取值范围内设定若干个离散的划分点,将取值范围划分为若干离散化的区间,分别用不同的符号或整数值代表落在每个子区间的数值。
常用的数据离散化方法主要有等宽法等频法

6.2.1.3 数据泛化处理

数据泛化处理指用高层次概念取代低层次概念的数据。
例如,年龄是一个低层次的概念,它经过泛化处理后会变成诸如青年、中年等高层次的概念。

6.2.1.4 Pandas中有关数据变换的基本操作
  • 轴向旋装
  • 分组与聚合
  • 哑变量处理
  • 面元划分

6.2.2 Pandas 数据标准化处理操作

6.2.2.1 最小-最大标准化(Min-Max Normalization)
  • 计算公式:

    X n o r m = X − X m i n X m a x − X m i n X_{norm} = \frac{X-X_{min}}{X_{max}-X_{min}} Xnorm​=Xmax​−Xmin​X−Xmin​​

    该操作将数据值映射到[0, 1]

  • 特点:

    1. 转化之后,大数据还是较大的,小数据还是较小的
    2. 当数据为最小值,转化为的数据为0
    3. 极差过大—>分母过大—>整体的数据偏小 —之间差异不太明显
    4. 如果数据中的某个数值很大,分母很大,–整体趋向于0
  • 实现方法:

    1. 自定义函数方式:
import pandas as pd 
import numpy as np
# 实现最小-最大标准化
def min_max_sca(data):"""最小标准化:param data: series/dataframe:return: 标准化之后的数据"""data = (data - data.min()) / (data.max() - data.min())return data
  • 实现方法:
    2. sklearn的MinMaxScaler方法

     from sklearn.preprocessing import MinMaxScalertool = MinMaxScaler(feature_range=(0, 1)) #根据需要设置最大最小值,这里设置最大值为1.最小值为0data = tool.fit_transform(values) #标准化,注意这里的values是array ```
  • 实现方法:
    3. 应用操作数据

df_Score = pd.read_csv("cj.txt",sep="\t")
df_Score
学号班级姓名性别英语体育军训数分高代解几
0230802424123080242成龙767877402360
1230802424423080242周怡669175474744
2230802425123080242张波858175454560
3230802424923080242朱浩655080726271
4230802421923080242封印738892614746
5230802420123080242迟培605089717671
6230802434723080243李华676184616578
7230802430723080243陈田767986694069
8230802432623080243余皓666785656171
9230802432023080243李嘉626090606777
10230802434223080243李上初769084606660
11230802431023080243郭窦796784646479
12230802443523080244姜毅涛777165617376
13230802443223080244赵宇747488687071
14230802444623080244周路768077617480
15230802442123080244林建祥727281639075
16230802443323080244李大强797677787070
17230802442823080244李侧通649691696077
18230802440223080244王慧737493707175
19230802442223080244李晓亮856085727283
20230802420123080242迟培605089717671
# 查看数据整体信息
df_Score.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 21 entries, 0 to 20
Data columns (total 10 columns):#   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 0   学号      21 non-null     int64 1   班级      21 non-null     int64 2   姓名      21 non-null     object3   性别      21 non-null     object4   英语      21 non-null     int64 5   体育      21 non-null     int64 6   军训      21 non-null     int64 7   数分      21 non-null     int64 8   高代      21 non-null     int64 9   解几      21 non-null     int64 
dtypes: int64(8), object(2)
memory usage: 1.8+ KB

调用自定义函数进行Min-Max标准化

# 获取英语成绩
score_English = df_Score["英语"]
# 调用自定义Min-Max标准化函数进行标准化
scoreScaled_English1 = min_max_sca(score_English)
scoreScaled_English1
0     0.64
1     0.24
2     1.00
3     0.20
4     0.52
5     0.00
6     0.28
7     0.64
8     0.24
9     0.08
10    0.64
11    0.76
12    0.68
13    0.56
14    0.64
15    0.48
16    0.76
17    0.16
18    0.52
19    1.00
20    0.00
Name: 英语, dtype: float64
scoreScaled_English1.describe()
count    21.000000
mean      0.478095
std       0.300527
min       0.000000
25%       0.240000
50%       0.520000
75%       0.640000
max       1.000000
Name: 英语, dtype: float64

调用sklearn的MinMaxScaler进行Min-Max标准化**

from sklearn.preprocessing import MinMaxScalertool = MinMaxScaler(feature_range=(0, 1)) #根据需要设置最大最小值,这里设置最大值为1.最小值为0
values = df_Score.loc[:,"英语":"解几"].values
scoresScaled = tool.fit_transform(values)
scoresScaled
array([[0.64      , 0.60869565, 0.42857143, 0.        , 0.        ,0.41025641],[0.24      , 0.89130435, 0.35714286, 0.18421053, 0.35820896,0.        ],[1.        , 0.67391304, 0.35714286, 0.13157895, 0.32835821,0.41025641],[0.2       , 0.        , 0.53571429, 0.84210526, 0.58208955,0.69230769],[0.52      , 0.82608696, 0.96428571, 0.55263158, 0.35820896,0.05128205],[0.        , 0.        , 0.85714286, 0.81578947, 0.79104478,0.69230769],[0.28      , 0.23913043, 0.67857143, 0.55263158, 0.62686567,0.87179487],[0.64      , 0.63043478, 0.75      , 0.76315789, 0.25373134,0.64102564],[0.24      , 0.36956522, 0.71428571, 0.65789474, 0.56716418,0.69230769],[0.08      , 0.2173913 , 0.89285714, 0.52631579, 0.65671642,0.84615385],[0.64      , 0.86956522, 0.67857143, 0.52631579, 0.64179104,0.41025641],[0.76      , 0.36956522, 0.67857143, 0.63157895, 0.6119403 ,0.8974359 ],[0.68      , 0.45652174, 0.        , 0.55263158, 0.74626866,0.82051282],[0.56      , 0.52173913, 0.82142857, 0.73684211, 0.70149254,0.69230769],[0.64      , 0.65217391, 0.42857143, 0.55263158, 0.76119403,0.92307692],[0.48      , 0.47826087, 0.57142857, 0.60526316, 1.        ,0.79487179],[0.76      , 0.56521739, 0.42857143, 1.        , 0.70149254,0.66666667],[0.16      , 1.        , 0.92857143, 0.76315789, 0.55223881,0.84615385],[0.52      , 0.52173913, 1.        , 0.78947368, 0.71641791,0.79487179],[1.        , 0.2173913 , 0.71428571, 0.84210526, 0.73134328,1.        ],[0.        , 0.        , 0.85714286, 0.81578947, 0.79104478,0.69230769]])
scoresScaled_English2=scoresScaled[:,0]
scoresScaled_English2
array([0.64, 0.24, 1.  , 0.2 , 0.52, 0.  , 0.28, 0.64, 0.24, 0.08, 0.64,0.76, 0.68, 0.56, 0.64, 0.48, 0.76, 0.16, 0.52, 1.  , 0.  ])
# 均值
scoresScaled_English2.mean()
0.47809523809523813
# 标准差
scoresScaled_English2.std()
0.29328385482520825
# 最小值
scoresScaled_English2.min()
0.0
# 最大值
scoresScaled_English2.max()
1.0
6.2.2.2 均值标准化(Z-Score Normalization)
  • 计算公式:

    z = x − μ σ z=\frac{x-\mu}{\sigma} z=σx−μ​

  • 特点:

    1. 标准化之后的数据不仅局限于[0,1],可以为正的,也可以为负的,总之,均值为0,标准差为1
    2. 不会影响数据的整体分布,大的值转化之后还是较大的,小的值转化之后还是较小的
  • 实现方法:

    1. 自定义函数方式
def stand_sca(data):"""标准差标准化数据:param data: series/datafrmae:return: 标准化之后的数据"""data = (data - data.mean()) / data.std()return data
  • 实现方法:
    2. sklearn的StandardScaler方法

     from sklearn.preprocessing import StandardScalerss=StandardScaler()Xtrain_data=ss.fit_transform(train_data)  #标准化训练集然后保存训练集的均值和方差Xtest_data=ss.transform(test_data)      #转换测试集数据print(ss.mean_)print(ss.var_)    
    
  • 实现方法:
    3. 应用操作数据

# df_Score #查看上面读取出的数据
scores = df_Score.iloc[:,4:10]
scores.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 21 entries, 0 to 20
Data columns (total 6 columns):#   Column  Non-Null Count  Dtype
---  ------  --------------  -----0   英语      21 non-null     int641   体育      21 non-null     int642   军训      21 non-null     int643   数分      21 non-null     int644   高代      21 non-null     int645   解几      21 non-null     int64
dtypes: int64(6)
memory usage: 1.1 KB
 # 调用自定义函数进行标准化
stand_sca(scores.values)
array([[ 0.43438518,  0.59257169,  0.51347844, -2.41297202, -3.75755737,-0.83110691],[-0.35654737,  1.62078402,  0.35529193, -1.85931923, -1.85931923,-2.096599  ],[ 1.14622448,  0.82985146,  0.35529193, -2.01750575, -2.01750575,-0.83110691],[-0.43564063, -1.62203947,  0.75075821,  0.11801216, -0.6729204 ,0.0389189 ],[ 0.19710542,  1.38350425,  1.69987727, -0.75201365, -1.85931923,-1.93841249],[-0.83110691, -1.62203947,  1.46259751,  0.0389189 ,  0.43438518,0.0389189 ],[-0.27745412, -0.75201365,  1.06713123, -0.75201365, -0.43564063,0.59257169],[ 0.43438518,  0.67166495,  1.22531774, -0.11926761, -2.41297202,-0.11926761],[-0.35654737, -0.27745412,  1.14622448, -0.43564063, -0.75201365,0.0389189 ],[-0.6729204 , -0.83110691,  1.54169076, -0.83110691, -0.27745412,0.51347844],[ 0.43438518,  1.54169076,  1.06713123, -0.83110691, -0.35654737,-0.83110691],[ 0.67166495, -0.27745412,  1.06713123, -0.51473389, -0.51473389,0.67166495],[ 0.51347844,  0.0389189 , -0.43564063, -0.75201365,  0.19710542,0.43438518],[ 0.27619867,  0.27619867,  1.38350425, -0.19836086, -0.04017435,0.0389189 ],[ 0.43438518,  0.75075821,  0.51347844, -0.75201365,  0.27619867,0.75075821],[ 0.11801216,  0.11801216,  0.82985146, -0.59382714,  1.54169076,0.35529193],[ 0.67166495,  0.43438518,  0.51347844,  0.59257169, -0.04017435,-0.04017435],[-0.51473389,  2.0162503 ,  1.62078402, -0.11926761, -0.83110691,0.51347844],[ 0.19710542,  0.27619867,  1.77897053, -0.04017435,  0.0389189 ,0.35529193],[ 1.14622448, -0.83110691,  1.14622448,  0.11801216,  0.11801216,0.98803797],[-0.83110691, -1.62203947,  1.46259751,  0.0389189 ,  0.43438518,0.0389189 ]])
# 调用sklearn库预处理函数
from sklearn.preprocessing import StandardScalerss=StandardScaler()
scores_scaled=ss.fit_transform(scores)
scores_scaled
array([[ 0.55204117,  0.44230299, -0.90469951, -2.50457384, -2.7077287 ,-0.95911099],[-0.81182525,  1.42399987, -1.19698705, -1.75012229, -1.0753181 ,-2.53882322],[ 1.77952094,  0.66884842, -1.19698705, -1.96567988, -1.21135231,-0.95911099],[-0.94821189, -1.67212106, -0.46626821,  0.94434751, -0.05506147,0.12694116],[ 0.14288124,  1.19745443,  1.287457  , -0.2412192 , -1.0753181 ,-2.34135919],[-1.6301451 , -1.67212106,  0.8490257 ,  0.83656872,  0.89717805,0.12694116],[-0.67543861, -0.84145447,  0.11830686, -0.2412192 ,  0.14898986,0.81806526],[ 0.55204117,  0.51781813,  0.41059439,  0.62101114, -1.55143786,-0.07052287],[-0.81182525, -0.3883636 ,  0.26445063,  0.18989597, -0.12307858,0.12694116],[-1.35737181, -0.91696961,  0.99516946, -0.34899799,  0.28502407,0.71933325],[ 0.55204117,  1.34848472,  0.11830686, -0.34899799,  0.21700697,-0.95911099],[ 0.96120109, -0.3883636 ,  0.11830686,  0.08211717,  0.08097275,0.91679727],[ 0.68842781, -0.08630302, -2.65842472, -0.2412192 ,  0.69312673,0.62060123],[ 0.27926789,  0.14024241,  0.70288193,  0.51323234,  0.4890754 ,0.12694116],[ 0.55204117,  0.59333328, -0.90469951, -0.2412192 ,  0.76114383,1.01552929],[ 0.0064946 , -0.01078788, -0.32012444, -0.02566162,  1.84941757,0.52186922],[ 0.96120109,  0.2912727 , -0.90469951,  1.59102027,  0.4890754 ,0.02820915],[-1.08459853,  1.80157559,  1.14131323,  0.62101114, -0.19109569,0.71933325],[ 0.14288124,  0.14024241,  1.43360077,  0.72878993,  0.55709251,0.52186922],[ 1.77952094, -0.91696961,  0.26445063,  0.94434751,  0.62510962,1.31172533],[-1.6301451 , -1.67212106,  0.8490257 ,  0.83656872,  0.89717805,0.12694116]])
print(ss.mean_)
print(ss.var_) 
[71.95238095 72.14285714 83.19047619 63.23809524 62.80952381 69.71428571]
[ 53.75963719 175.36054422  46.82086168  86.0861678  216.15419501102.58503401]
# 转换前数据统计信息
scores.describe()
英语体育军训数分高代解几
count21.00000021.00000021.00000021.00000021.00000021.000000
mean71.95238172.14285783.19047663.23809562.80952469.714286
std7.51316313.5693987.0115559.50739115.06525510.378549
min60.00000050.00000065.00000040.00000023.00000044.000000
25%66.00000061.00000077.00000061.00000060.00000069.000000
50%73.00000074.00000084.00000064.00000066.00000071.000000
75%76.00000080.00000089.00000070.00000072.00000077.000000
max85.00000096.00000093.00000078.00000090.00000083.000000
# 转换后数据均值
scores_scaled.mean(axis=0)
array([ 4.75809868e-16,  3.06633026e-16,  1.21595855e-16, -2.85485921e-16,-3.70074342e-17,  6.06657581e-16])
# 转换后数据标准差
scores_scaled.std(axis=0)
array([1., 1., 1., 1., 1., 1.])
6.2.2.3 小数定标标准化
  • 通过移动小数点的位置来进行数据转化,将数据转化为[-1,1]之间

  • 小数点移动的位数 取决于该列数据绝对值的最大值

  • 计算公式:

    X ∗ = X 1 0 k X^{*}=\frac{X}{10^{k}} X∗=10kX​

  • 实现方法:

# 实现小数定标标准化
def desc_sca(data):"""小数定标标准化:param data: series/dataframe:return: 标准化之后的数据"""# abs() --取绝对值# np.ceil --向上取整data = data / (10 ** (int(np.ceil(np.log10(data.abs().max())))))return data
# 查看前面的数据库
#scores
scores_scaled3 = desc_sca(scores.loc[:,"英语"])
#scores_scaled3
scores_scaled3
0     0.76
1     0.66
2     0.85
3     0.65
4     0.73
5     0.60
6     0.67
7     0.76
8     0.66
9     0.62
10    0.76
11    0.79
12    0.77
13    0.74
14    0.76
15    0.72
16    0.79
17    0.64
18    0.73
19    0.85
20    0.60
Name: 英语, dtype: float64

6.2.3 Pandas数据离散化处理操作

某些模型算法,要求数据是离散的,此时就需要将连续型特征(数值型)变换成离散型特征(类别型)。

连续特征的离散化就是在数据的取值范围内设定若干个离散的划分点,将取值范围划分为一些离散化的区间,最后用不同的符号或整数值代表落在每个子区间中的数据值。

因此离散化涉及两个子任务,即确定分类数以及如何将连续型数据映射到这些类别型数据上

离散化处理的必要性:

  • 节约计算资源,提高计算效率。
  • 算法模型(尤其是分类模型)的计算需要。虽然很多模型,例如决策树可以支持输入连续型数据,但是决策树本身会先将连续型数据转化为离散型数据,因此离散化转换是一个必要步骤。
  • 增强模型的稳定性和准确度。数据离散化之后,处于异常状态的数据不会明显突出异常特征,而是会被划分为一个子集中的一部分,因此异常数据对模型的影响会大大降低,尤其是基于距离计算的模型(例如K均值、协同过滤等)效果明显。
  • 特定数据处理和分析的必要步骤,尤其在图像处理方面应用广泛。大多数图像做特征检测(以及其他基于特征的分析)时,都需要先将图像做二值化处理,二值化也是离散化的一种。
  • 模型结果应用和部署的需要。如果原始数据的值域分布过多,或值域划分不符合业务逻辑,那么模型结果将很难被业务理解并应用。
6.2.3.1 时间数据的离散化

时间数据的离散化主要用于以时间为主要特征的数据集中和粒
度转换,离散化处理后将分散的时间特征转换为更高层次的时间特征。
在带有时间的数据集中,时间可能作为行记录的序列,也可能作为
列(维度)记录数据特征。常见的针对时间数据的离散化操作分为两
类:

  • 针对一天中的时间离散化。一般是将时间戳转换为秒、分钟、小
    时或上下午。
  • 针对日粒度以上数据的离散化。一般是将日期转化为周数、周
    几、月、工作日或休息日、季度、年等。

针对时间数据的离散化可以将细粒度的时间序列数据离散化为粗粒
度的三类数据:

  • 离散化为分类数据,例如上午、下午;
  • 离散化为顺序数据,例如周一、周二、周三;
  • 离散化为数值型数据,例如一年有52个周,周数是数值型数据。
import pandas as pd
from sklearn import preprocessing# 读取数据
df = pd.read_table('data7.txt', names=['id', 'amount', 'income', 'datetime', 'age'])  # 读取数据文件
print (df.head(5))  # 打印输出前5条数据
      id  amount  income             datetime    age
0  15093    1390   10.40  2017-04-30 19:24:13   0-10
1  15062    4024    4.68  2017-04-27 22:44:59  70-80
2  15028    6359    3.84  2017-04-27 10:07:55  40-50
3  15012    7759    3.70  2017-04-04 07:28:18  30-40
4  15021     331    4.25  2017-04-08 11:14:00  70-80

将datetime数据离散化为星期几

  • 方法 1 :使用 pd.to_datetime 及 dt.dayofweek
# 将数据转成 datetime 类型
df['datetime'] = pd.to_datetime(df['datetime'])# 显示 周几 
df['dow'] = df['datetime'].dt.dayofweek# 查看前5行
df.head()
idamountincomedatetimeagedow
015093139010.402017-04-30 19:24:130-106
11506240244.682017-04-27 22:44:5970-803
21502863593.842017-04-27 10:07:5540-503
31501277593.702017-04-04 07:28:1830-401
4150213314.252017-04-08 11:14:0070-805
  • 方法 2:纯手工打造
# 将时间转换为datetime格式,Python3中,map返回一个迭代器,所以需要list一下,把其中的值取出来
df['datetime'] = list(map(pd.to_datetime,df['datetime']))
# 离散化为 周几 的格式
df['datetime']= [i.weekday() for i in df['datetime']]# 查看前5行
df.head()
idamountincomedatetimeagedow
015093139010.4060-106
11506240244.68370-803
21502863593.84340-503
31501277593.70130-401
4150213314.25570-805
6.2.3.2 连续数据的离散化

连续数据的离散化结果可以分为两类:

  • 一类是将连续数据划分为特定区间的集合,例如{(0,10],(10,20],(20,50],(50,100]}

  • 一类是将连续数据划分为特定类,例如类1、类2、类3

常见实现针对连续数据化离散化的方法如下:

  • 分位数法:使用四分位、五分位、十分位等分位数进行离散化处理

  • 距离区间法:可使用等距区间或自定义区间的方式进行离散化,该方法(尤其是等距区间)可以较好地保持数据原有的分布

  • 频率区间法:将数据按照不同数据的频率分布进行排序,然后按照等频率或指定频率离散化,这种方法会把数据变换成均匀分布。好处是各区间的观察值是相同的,不足会改变了原有数据的分布状态。每个桶里的数值个数是相同的

  • 聚类法:例如使用 K 均值将样本集分为多个离散化的簇

6.2.3.2.1 距离区间法:自定义分箱区间实现离散化

使用pd.cut进行分箱。

  • pd.cut()基本语法:
 pandas.cut(x,bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False, duplicates='raise')
  • pd.cut()参数说明:

    • x:被切分的类数组(array-like)数据,必须是1维的(不能用DataFrame);

    • bins:bins是被切割后的区间(或者叫“桶”、“箱”、“面元”),有3中形式:一个int型的标量、标量序列(数组)或者pandas.IntervalIndex 。

      • 一个int型的标量
        当bins为一个int型的标量时,代表将x平分成bins份。x的范围在每侧扩展0.1%,以包括x的最大值和最小值。
      • 标量序列
        标量序列定义了被分割后每一个bin的区间边缘,此时x没有扩展。
      • pandas.IntervalIndex
        定义要使用的精确区间。
    • right:bool型参数,默认为True,表示是否包含区间右部。比如如果bins=[1,2,3],right=True,则区间为(1,2],(2,3];right=False,则区间为(1,2),(2,3)。

    • labels:给分割后的bins打标签,比如把年龄x分割成年龄段bins后,可以给年龄段打上诸如青年、中年的标签。labels的长度必须和划分后的区间长度相等,比如bins=[1,2,3],划分后有2个区间(1,2],(2,3],则labels的长度必须为2。如果指定

    • labels=False,则返回x中的数据在第几个bin中(从0开始)。

    • retbins:bool型的参数,表示是否将分割后的bins返回,当bins为一个int型的标量时比较有用,这样可以得到划分后的区间,默认为False。

    • precision:保留区间小数点的位数,默认为3.

    • include_lowest:bool型的参数,表示区间的左边是开还是闭的,默认为false,也就是不包含区间左部(闭)。

    • duplicates:是否允许重复区间。有两种选择:raise:不允许,drop:允许。

  • 返回值:

    • out:一个pandas.Categorical, Series或者ndarray类型的值,代表分区后x中的每个值在哪个bin(区间)中,如果指定了labels,则返回对应的label。
    • bins:分隔后的区间,当指定retbins为True时返回。
df.head(3)
idamountincomedatetimeagedow
015093139010.4060-106
11506240244.68370-803
21502863593.84340-503

将amount离散化

# 自定义区间边界
bins = [0, 200, 1000, 5000, 10000]
# 按照给定区间 使用 pd.cut 将数据进行离散化
df['amount_grp1'] = pd.cut(df['amount'], bins=bins)
df.head()
idamountincomedatetimeagedowamount_grp1
015093139010.4060-106(1000, 5000]
11506240244.68370-803(1000, 5000]
21502863593.84340-503(5000, 10000]
31501277593.70130-401(5000, 10000]
4150213314.25570-805(200, 1000]
# bins传递整数标量
# 按照给定区间 使用 pd.cut 将数据进行离散化
df['amount_grp2'] = pd.cut(df['amount'], bins=10)
df.head()
idamountincomedatetimeagedowamount_grp1amount_grp2
015093139010.4060-106(1000, 5000](953.6, 1731.2]
11506240244.68370-803(1000, 5000](3286.4, 4064.0]
21502863593.84340-503(5000, 10000](5619.2, 6396.8]
31501277593.70130-401(5000, 10000](7174.4, 7952.0]
4150213314.25570-805(200, 1000](168.224, 953.6]
# 实现离散化 并添加自定义标签
bins = [0, 200, 1000, 5000, 10000]
labels = [  '<200', '200~1000','1000~5000','5000~10000']
# 按照给定区间 使用 pd.cut 将数据进行离散化
# right == False : 左闭右开,不加此项,默认为左开右闭的
df['amount_level'] = pd.cut(df.amount, bins=bins,labels=labels,right=False)
df.head()
idamountincomedatetimeagedowamount_grp1amount_grp2amount_level
015093139010.4060-106(1000, 5000](953.6, 1731.2]1000~5000
11506240244.68370-803(1000, 5000](3286.4, 4064.0]1000~5000
21502863593.84340-503(5000, 10000](5619.2, 6396.8]5000~10000
31501277593.70130-401(5000, 10000](7174.4, 7952.0]5000~10000
4150213314.25570-805(200, 1000](168.224, 953.6]200~1000
6.2.3.2.2 频率区间法:按照等频率或指定频率离散化

使用pd.qcut()函数进行处理。

  • pd.qcut()基本语法:
pandas.qcut(x, q,labels=None, retbins=False, precision=3, duplicates='raise') 
  • pd.qcut()参数说明:

    • x :一维数组或者Serise

    • q : 表示分位数的整数或者数组,

      • 如果是分位数的整数,例如10用于十分位,4用于四分位
      • 如果是分位数数组,例如[0,0.25,0.5,0.75,1]用于四分位数
    • labels : 数组或者布尔值,默认为none,用于指定每个箱体的标签

      • 如果是数组,长度要与分箱个数一致,比如用四分位数分箱,需要指定四个标签
      • 如果为False,则仅返回分箱的整数指示符,即当前数据位于哪个箱子中
    • rebines :布尔值,可选。 是否显示分箱的分界值。(由于是按照分位数进行分箱,在不知道分位数具体数值的情况下,可以通过这个参数设置显示分界值即分位数的具体数值)

    • precision:整数,默认3,存储和显示分箱标签的精度。

    • duplicates:如果分箱临界值不唯一,则引发ValueError或丢弃非唯一

  • 返回值:

    • out:一个pandas.Categorical, Series或者ndarray类型的值,代表分区后x中的每个值在哪个bin(区间)中,如果指定了labels,则返回对应的label。
    • bins:分隔后的区间,当指定retbins为True时返回。
df.head()
idamountincomedatetimeagedowamount_grp1amount_grp2amount_level
015093139010.4060-106(1000, 5000](953.6, 1731.2]1000~5000
11506240244.68370-803(1000, 5000](3286.4, 4064.0]1000~5000
21502863593.84340-503(5000, 10000](5619.2, 6396.8]5000~10000
31501277593.70130-401(5000, 10000](7174.4, 7952.0]5000~10000
4150213314.25570-805(200, 1000](168.224, 953.6]200~1000
df['amount_grp3'] = pd.qcut(df['amount'], 4, labels=['bad', 'medium', 'good', 'awesome'])
df.head()
idamountincomedatetimeagedowamount_grp1amount_grp2amount_levelamount_grp3
015093139010.4060-106(1000, 5000](953.6, 1731.2]1000~5000bad
11506240244.68370-803(1000, 5000](3286.4, 4064.0]1000~5000good
21502863593.84340-503(5000, 10000](5619.2, 6396.8]5000~10000awesome
31501277593.70130-401(5000, 10000](7174.4, 7952.0]5000~10000awesome
4150213314.25570-805(200, 1000](168.224, 953.6]200~1000bad
6.2.3.2.3 聚类法实现离散化

sklearn中的KMeans详细介绍见知乎上的机器学习之SKlearn(scikit-learn)的K-means聚类算法

from sklearn.cluster import KMeans# 获取要聚类的数据
df_clu = df[['amount']]# 创建 KMeans 模型并指定要聚类数量
model_kmeans = KMeans(n_clusters=4, random_state=111)# 建模聚类
kmeans_result = model_kmeans.fit_predict(df_clu)# 将新离散化的数据合并到原数据框
df['amount_grp4'] = kmeans_resultdf.head()
idamountincomedatetimeagedowamount_grp1amount_grp2amount_levelamount_grp3amount_grp4
015093139010.4060-106(1000, 5000](953.6, 1731.2]1000~5000bad2
11506240244.68370-803(1000, 5000](3286.4, 4064.0]1000~5000good0
21502863593.84340-503(5000, 10000](5619.2, 6396.8]5000~10000awesome1
31501277593.70130-401(5000, 10000](7174.4, 7952.0]5000~10000awesome1
4150213314.25570-805(200, 1000](168.224, 953.6]200~1000bad2

6.2.4 Pandas数据泛化处理操作

数据泛化:把较低层次的概念层(例如:年龄的数值范围)用较高层次的概念(例如:青年、中年和 老年)替换来汇总数据。或者通过减少维度在设计较少维度的概念空间汇总数据(例如汇总学生组群时,删除生日和电话号码属性)

数据泛化处理的常用方法也一般是数据离散化处理方法。

更多推荐

第6章 数据集成、变换与规约1

本文发布于:2024-02-27 06:04:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1705463.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:规约   数据

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!