3.7 合并数据集: Concat与Append操作

- pd.concat
- pd.merge
- pd.join
import pandas as pd
def make_df(cols,ind):data = {c: [str(c) + str(i) for i in ind]for c in cols}return pd.DataFrame(data,ind)     # 用字典创建DataFrame
make_df('ABC',range(3))
A B C
0 A0 B0 C0
1 A1 B1 C1
2 A2 B2 C2

3.7.1 知识回顾: NumPy数组的合并

用np.concatenate完成
- 第一个参数表示要合并的数组或元组, 第二个参数表示合并的坐标轴方向

import pandas as pd
import numpy as np
x = [1,2,3]
y = [4,5,6]
z = [7,8,9]
np.concatenate([x,y,z])
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
x = [[1,2],[3,4]]
np.concatenate([x,x], axis=1)
array([[1, 2, 1, 2],[3, 4, 3, 4]])

3.7.2 通过pd.concat实现简易合并

- Pandas中的pd.concat()函数与np.concatenate()类似, 配置参数更多,功能更强大.

pd.concat()可以简单的合并一维的Series和DataFrame对象

ser1 = pd.Series(['a','b','c'],index=[1,2,3])
ser2 = pd.Series(['d','e','f'],index=[4,5,6])
pd.concat([ser1,ser2])
1    a
2    b
3    c
4    d
5    e
6    f
dtype: object
ser1 = pd.Series(['a','b','c'],index=[1,2,3])
ser2 = pd.Series(['d','e','f'],index=[4,5,6])
ser1 + ser2
1    NaN
2    NaN
3    NaN
4    NaN
5    NaN
6    NaN
dtype: object
ser1 = pd.Series(['a','b','c'],index=[1,2,3])
ser2 = pd.Series(['d','e','f'],index=[1,2,3])
ser1 + ser2
1    ad
2    be
3    cf
dtype: object
df1 = make_df('AB',[1,2])
df2 = make_df('AB',[3,4])
print(df1);print(df2);print(pd.concat([df1,df2]))
    A   B
1  A1  B1
2  A2  B2A   B
3  A3  B3
4  A4  B4A   B
1  A1  B1
2  A2  B2
3  A3  B3
4  A4  B4
df1 = make_df('AB',[1,2])
df2 = make_df('BD',[3,4])
print(df1);print(df2);print(pd.concat([df1,df2]))
    A   B
1  A1  B1
2  A2  B2B   D
3  B3  D3
4  B4  D4A   B    D
1   A1  B1  NaN
2   A2  B2  NaN
3  NaN  B3   D3
4  NaN  B4   D4D:\Anaconda3\lib\site-packages\ipykernel_launcher.py:3: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version
of pandas will change to not sort by default.To accept the future behavior, pass 'sort=True'.To retain the current behavior and silence the warning, pass sort=FalseThis is separate from the ipykernel package so we can avoid doing imports until

索引重叠

np.concatenate与pd.concat最主要的差异是,Pandas在合并时会保留索引, 即使索引是重复的.

x = make_df('AB',[0,1])
y = make_df('AB',[2,3])
y.index = x.index
print(x);print(y);print(pd.concat([x,y]))
    A   B
0  A0  B0
1  A1  B1A   B
0  A2  B2
1  A3  B3A   B
0  A0  B0
1  A1  B1
0  A2  B2
1  A3  B3

捕捉索引重复的错误: 可以设置verify_integrity参数. 将参数设置为true. 合并时若有重复就会触发异常.

try:pd.concat([x,y],verify_integrity=True)
except ValueError as e:print('ValueError:',e)
ValueError: Indexes have overlapping values: Int64Index([0, 1], dtype='int64')

忽略索引: 设置ignore_index参数, 设置为True是会创建一个新的整数索引

pd.concat([x,y],ignore_index=True)
A B
0 A0 B0
1 A1 B1
2 A2 B2
3 A3 B3

增加多级索引: 通过keys参数为数据源设置多级索引

print(x);print(y);print(pd.concat([x,y],keys=['x','y']))
    A   B
0  A0  B0
1  A1  B1A   B
0  A2  B2
1  A3  B3A   B
x 0  A0  B01  A1  B1
y 0  A2  B21  A3  B3

类似join的合并

df5 = make_df('ABC',[1,2])
df6 = make_df('BCD',[3,4])
print(df5);print(df6);print(pd.concat([df5,df6]))
    A   B   C
1  A1  B1  C1
2  A2  B2  C2B   C   D
3  B3  C3  D3
4  B4  C4  D4A   B   C    D
1   A1  B1  C1  NaN
2   A2  B2  C2  NaN
3  NaN  B3  C3   D3
4  NaN  B4  C4   D4D:\Anaconda3\lib\site-packages\ipykernel_launcher.py:3: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version
of pandas will change to not sort by default.To accept the future behavior, pass 'sort=True'.To retain the current behavior and silence the warning, pass sort=FalseThis is separate from the ipykernel package so we can avoid doing imports until

设置join参数为inner或者outer

print(df5);print(df6);print(pd.concat([df5,df6],join='inner'))
    A   B   C
1  A1  B1  C1
2  A2  B2  C2B   C   D
3  B3  C3  D3
4  B4  C4  D4B   C
1  B1  C1
2  B2  C2
3  B3  C3
4  B4  C4

直接确定结果使用的列

print(df5);print(df6);print(pd.concat([df5,df6],join_axes=[df5.columns]))
    A   B   C
1  A1  B1  C1
2  A2  B2  C2B   C   D
3  B3  C3  D3
4  B4  C4  D4A   B   C
1   A1  B1  C1
2   A2  B2  C2
3  NaN  B3  C3
4  NaN  B4  C4
print(df1);print(df2);print(df1.append(df2))
    A   B
1  A1  B1
2  A2  B2A   B
3  A3  B3
4  A4  B4A   B
1  A1  B1
2  A2  B2
3  A3  B3
4  A4  B4

3.8 合并数据集: 合并与连接

- Pandas的主要接口是pd.merge()函数

3.8.1 关系代数

pd.merge()实现的功能基于关系代数的一部分. 关系代数式处理关系型数据的通用理论,绝大部分数据库的可用操作都以此为理论基础. 关系代数方法论的强大之处在于, 它提出的若干简单的操作规则经过组合就可以为任意数据构建十分复杂的操作.
Pandas在pd.merge()函数与Series和DataFrame的join()方法里实现了这些基本操作规则.

3.8.2 数据连接的类型

pd.merge()函数实现三种数据连接的类型: 一对一,多对一和多对多.

** 一对一连接 **

import pandas as pd
df1 = pd.DataFrame({'雇员':['张三','李四','王五','赵六'],'部门':['生产','技术','技术','人力']})   # 需要加大括号
df2 = pd.DataFrame({'雇员':['赵六','李四','张三','王五'],'入职年份':[2010,2011,2012,2011]})
print(df1);print(df2)
   雇员  部门
0  张三  生产
1  李四  技术
2  王五  技术
3  赵六  人力雇员  入职年份
0  赵六  2010
1  李四  2011
2  张三  2012
3  王五  2011
df3 = pd.merge(df1,df2)
print(df3)
   雇员  部门  入职年份
0  张三  生产  2012
1  李四  技术  2011
2  王五  技术  2011
3  赵六  人力  2010

pd.merge()方法会发现两个DataFrame都有’雇员’列, 并自动以这列为键进行连接. 两个输入的合并结果是一个新的DataFrame. 共同列的位置可以不一致.
pd.merge()会默认丢弃原来的行索引, 不过也可以自定义.

多对一连接 能否也叫一对多连接

需要连接的两个列中, 有一列的值有重复. 通过多对一连接获得的结果DataFrame将会保留重复值.

df4 = pd.DataFrame({'部门':['生产','技术','人力'],'负责人':['生产经理','技术经理','人力经理']})
print(df3);print(df4);print(pd.merge(df3,df4))
   雇员  部门  入职年份
0  张三  生产  2012
1  李四  技术  2011
2  王五  技术  2011
3  赵六  人力  2010部门   负责人
0  生产  生产经理
1  技术  技术经理
2  人力  人力经理雇员  部门  入职年份   负责人
0  张三  生产  2012  生产经理
1  李四  技术  2011  技术经理
2  王五  技术  2011  技术经理
3  赵六  人力  2010  人力经理

多对多连接

df5 = pd.DataFrame({'部门':['生产','生产','技术','技术','人力','人力'],'子部门':['生产1','生产2','技术1','技术2','人力1','人力2']})
print(df1);print(df5);print(pd.merge(df1,df5))
   雇员  部门
0  张三  生产
1  李四  技术
2  王五  技术
3  赵六  人力部门  子部门
0  生产  生产1
1  生产  生产2
2  技术  技术1
3  技术  技术2
4  人力  人力1
5  人力  人力2雇员  部门  子部门
0  张三  生产  生产1
1  张三  生产  生产2
2  李四  技术  技术1
3  李四  技术  技术2
4  王五  技术  技术1
5  王五  技术  技术2
6  赵六  人力  人力1
7  赵六  人力  人力2

3.8.3 设置数据合并的键

pd.merge()的默认行为, 它会将两个输入的一个或多个共同列作为键进行合并. 但由于两个输入要合并的列通常都不是同名的, 因此pd.merge()提供了一些参数处理这个问题.

参数on的用法
- 这个参数只能在两个DataFrame有共同列名的时候才可以使用.

print(df1);print(df2);print(pd.merge(df1,df2,on='雇员'))
   雇员  部门
0  张三  生产
1  李四  技术
2  王五  技术
3  赵六  人力雇员  入职年份
0  赵六  2010
1  李四  2011
2  张三  2012
3  王五  2011雇员  部门  入职年份
0  张三  生产  2012
1  李四  技术  2011
2  王五  技术  2011
3  赵六  人力  2010

left_on与right_on参数
- 有时候也需要合并两个列名不同的数据集.

df3 = pd.DataFrame({'姓名':['张三','李四','王五','赵六'],'工资':[5000,6000,7000,5500]})
print(df1);print(df2);print(pd.merge(df1,df3,left_on='雇员',right_on='姓名'))
   雇员  部门
0  张三  生产
1  李四  技术
2  王五  技术
3  赵六  人力雇员  入职年份
0  赵六  2010
1  李四  2011
2  张三  2012
3  王五  2011雇员  部门  姓名    工资
0  张三  生产  张三  5000
1  李四  技术  李四  6000
2  王五  技术  王五  7000
3  赵六  人力  赵六  5500

汇总的结果会多一列, 可以用drop()方法去掉.

pd.merge(df1,df3,left_on='雇员',right_on='姓名').drop('姓名',axis=1)
雇员 部门 工资
0 张三 生产 5000
1 李四 技术 6000
2 王五 技术 7000
3 赵六 人力 5500

left_index与right_index参数
- 除了合并列之外, 还可以合并索引.

df1a = df1.set_index('雇员')
df2a = df2.set_index('雇员')
print(df1a);print(df2a)
    部门
雇员
张三  生产
李四  技术
王五  技术
赵六  人力入职年份
雇员
赵六  2010
李四  2011
张三  2012
王五  2011

可以通过设置pd.merge()中的left_index或right_index参数将索引设置为键来实现合并.

print(df1a);print(df2a);
print(pd.merge(df1a,df2a,left_index=True,right_index=True))  # 是True , 不是 = 索引的名称
    部门
雇员
张三  生产
李四  技术
王五  技术
赵六  人力入职年份
雇员
赵六  2010
李四  2011
张三  2012
王五  2011部门  入职年份
雇员
张三  生产  2012
李四  技术  2011
王五  技术  2011
赵六  人力  2010

为了方便考虑, DataFrame实现了join()方法, 它可以按照索引进行数据合并.

print(df1a);print(df2a);print(df1a.join(df2a))
    部门
雇员
张三  生产
李四  技术
王五  技术
赵六  人力入职年份
雇员
赵六  2010
李四  2011
张三  2012
王五  2011部门  入职年份
雇员
张三  生产  2012
李四  技术  2011
王五  技术  2011
赵六  人力  2010

如果想将索引与列混合使用, 可以使用left_index与right_on, 或者结合left_on与right_index

print(df1a);print(df3)
print(pd.merge(df1a,df3,left_index=True,right_on='姓名'))    # 多个索引怎么办
    部门
雇员
张三  生产
李四  技术
王五  技术
赵六  人力姓名    工资
0  张三  5000
1  李四  6000
2  王五  7000
3  赵六  5500部门  姓名    工资
0  生产  张三  5000
1  技术  李四  6000
2  技术  王五  7000
3  人力  赵六  5500

3.8.4 设置数据连接的集合操作规则

df6 = pd.DataFrame({'姓名':['张三','李四','王五','赵六'],'食物':['鱼','西瓜','冬瓜','大头菜']})
df7 = pd.DataFrame({'姓名':['张三','老李'],'喝酒':['白酒','红酒']})
print(df6);print(df7);print(pd.merge(df6,df7))
   姓名   食物
0  张三    鱼
1  李四   西瓜
2  王五   冬瓜
3  赵六  大头菜姓名  喝酒
0  张三  白酒
1  老李  红酒姓名 食物  喝酒
0  张三  鱼  白酒

和别的两个数据集, 在’姓名’列中只有一个共同的值’张三’. 默认情况下, 结果中只出现会包含两个输入集合的交集(inner join). 这种连接方式被称为内连接. 我们可以通过how参数设置连接方式,默认为’inner’

pd.merge(df6,df7,how='inner')
姓名 食物 喝酒
0 张三 白酒

how参数支持的连接方式: outer, left,inner 和right.
- outer(外连接)返回两个输入列的并集, 所有缺失值都用NaN填充.

print(df6);print(df7);print(pd.merge(df6,df7,how='outer'))
   姓名   食物
0  张三    鱼
1  李四   西瓜
2  王五   冬瓜
3  赵六  大头菜姓名  喝酒
0  张三  白酒
1  老李  红酒姓名   食物   喝酒
0  张三    鱼   白酒
1  李四   西瓜  NaN
2  王五   冬瓜  NaN
3  赵六  大头菜  NaN
4  老李  NaN   红酒

left join(左连接), right join(右连接)返回的结果分别只包括左列和右列

print(df6);print(df7);print(pd.merge(df6,df7,how='left'))
   姓名   食物
0  张三    鱼
1  李四   西瓜
2  王五   冬瓜
3  赵六  大头菜姓名  喝酒
0  张三  白酒
1  老李  红酒姓名   食物   喝酒
0  张三    鱼   白酒
1  李四   西瓜  NaN
2  王五   冬瓜  NaN
3  赵六  大头菜  NaN

3.8.5 重复列名: suffixes参数

- 可能会遇到两个输入DataFrame有重名列的情况.
df8 = pd.DataFrame({'name':['bob','jake','lisa','sue'],'rank':[1,2,3,4]})
df9 = pd.DataFrame({'name':['bob','jake','lisa','sue'],'rank':[3,1,4,2]})
print(df8);print(df9);print(pd.merge(df8,df9,on='name'))
   name  rank
0   bob     1
1  jake     2
2  lisa     3
3   sue     4name  rank
0   bob     3
1  jake     1
2  lisa     4
3   sue     2name  rank_x  rank_y
0   bob       1       3
1  jake       2       1
2  lisa       3       4
3   sue       4       2

当有两个重复的列名, pd.merge()函数会自动为它们增加后缀_x _y.
也可以通过suffixes参数自定义后缀

pd.merge(df8,df9,on='name',suffixes=['_l','_r'])
name rank_l rank_r
0 bob 1 3
1 jake 2 1
2 lisa 3 4
3 sue 4 2

3.8.6 案例: 美国各州的统计数据

# 文件路径不能有中文
pop = pd.read_csv(r'E:\Python\state-population.csv')
areas = pd.read_csv(r'E:\Python\state-abbrevs.csv')
abbrevs = pd.read_csv(r'E:\Python\state-areas.csv')
print(pop.head());print(areas.head());print(abbrevs.head())
  state/region     ages  year  population
0           AL  under18  2012   1117489.0
1           AL    total  2012   4817528.0
2           AL  under18  2010   1130966.0
3           AL    total  2010   4785570.0
4           AL  under18  2011   1125763.0state abbreviation
0     Alabama           AL
1      Alaska           AK
2     Arizona           AZ
3    Arkansas           AR
4  California           CAstate  area (sq. mi)
0     Alabama          52423
1      Alaska         656425
2     Arizona         114006
3    Arkansas          53182
4  California         163707
merged = pd.merge(pop,areas,how='outer',left_on='state/region',right_on='abbreviation')
merged = merged.drop('abbreviation',1)   # 参数1不能少
print(merged.head())
  state/region     ages  year  population    state
0           AL  under18  2012   1117489.0  Alabama
1           AL    total  2012   4817528.0  Alabama
2           AL  under18  2010   1130966.0  Alabama
3           AL    total  2010   4785570.0  Alabama
4           AL  under18  2011   1125763.0  Alabama

检查每个字段是否有缺失值

merged.isnull().any()
state/region    False
ages            False
year            False
population       True
state            True
dtype: bool

部分population是缺失值, 查看是哪些数据缺失值

merged[merged['population'].isnull()].head()
state/region ages year population state
2448 PR under18 1990 NaN NaN
2449 PR total 1990 NaN NaN
2450 PR total 1991 NaN NaN
2451 PR under18 1991 NaN NaN
2452 PR total 1993 NaN NaN
merged.loc[merged['state'].isnull(),'state/region'].unique()
array(['PR', 'USA'], dtype=object)
merged.loc[merged['state/region'] == 'PR','state'] = 'Puerto Rico'
merged.loc[merged['state/region'] == 'USA','state'] = 'Uinted States'
merged.isnull().any()
state/region    False
ages            False
year            False
population       True
state           False
dtype: bool
final = pd.merge(merged,abbrevs,on='state',how='left')
final.head()
state/region ages year population state area (sq. mi)
0 AL under18 2012 1117489.0 Alabama 52423.0
1 AL total 2012 4817528.0 Alabama 52423.0
2 AL under18 2010 1130966.0 Alabama 52423.0
3 AL total 2010 4785570.0 Alabama 52423.0
4 AL under18 2011 1125763.0 Alabama 52423.0
data2010 = final.query("year == 2010 & ages == 'total'")
data2010.head()
state/region ages year population state area (sq. mi)
3 AL total 2010 4785570.0 Alabama 52423.0
91 AK total 2010 713868.0 Alaska 656425.0
101 AZ total 2010 6408790.0 Arizona 114006.0
189 AR total 2010 2922280.0 Arkansas 53182.0
197 CA total 2010 37333601.0 California 163707.0
# data2010.set_index('state',inplace=True)    # 为什么报错
# density = data2010['population'] / data2010['area(sq.mi)']
# density.sort_values(ascending=False,inplace=True)
# density.head()

第3章 Pandas数据处理(3.7-3.8)_Python数据科学手册学习笔记相关推荐

  1. 用《R数据科学》学习一套数据处理语法

    这套语法就叫 tidyverse,先用一套小抄 Cheat Sheet 来镇贴. 抛开社区讲语言都是耍流氓,比如说 Python 可以克隆 ggplot2 包,语法几乎一样,用起来不会有太大的差别,但 ...

  2. 【Python数据科学】第三章 Pandas 数据处理(下半章)

    7.合并数据集:合并与连接 Pandas 的基本特性之一就是高性能的内存式数据连接(join)和合并(merge)操作.如果你有使用数据库的经验,那么对这类操作一定很熟悉.Pandas 的主接口是pd ...

  3. 可视化导论 - 第四章 数据可视化流程 - 学习笔记

    第4章 数据可视化流程 4.1 数据可视化流程 以数据流向为主线,其主要模块包括数据采集.数据处理和变换.可视化映射和用户感知. 4.2 数据处理和数据变换 4.2.1 数据滤波 数据滤波器在信号处理 ...

  4. python降维将多列数据压缩为一列_Python机器学习(Sebastian著 ) 学习笔记——第五章通过降维压缩数据(Windows Spyder Python 3.6)...

    数据压缩是机器学习领域中重要的内容,通过数据压缩技术可以将原始数据集变换到一个维度更低的新的特征子空间,帮助对数据存储和分析. 降维压缩数据,分为无监督和有监督两类,先来介绍无监督数据压缩--主成分分 ...

  5. java从入门到精通第11章_《Java从入门到精通》第十章学习笔记

    第10章 Java集合类 一.概述 Java中的java.util包中提供了一些集合类,也被称为容器,不同于数组,集合的长度是可变的,存放的是对象的引用.常用的集合有List集合.Set集合.Map集 ...

  6. pandas 在某个列表中的值 筛选列_Pandas学习笔记(二)

    前言 上一篇研究了如何构建一个Pandas的Series和DataFrame,之后对DataFrame的行列选择及增加删除行为进行了探索,这一节将从如何对DataFrame进行条件选择开始. 条件选择 ...

  7. 【Python数据科学手册】Pandas——十二、处理时间序列

    文章目录 十二.处理时间序列 1.Python的日期与时间工具 1)Python原生的日期使劲按工具:datetime和dateutil 2)时间类型数组:Numpy的datetime64类型 3)p ...

  8. 用python画统计图表_Python数据科学(九)- 使用Pandas绘制统计图表

    作者:许胜利 Python爱好者社区专栏作者 博客专栏:许胜利的博客专栏 1.信息可视化 因为人对图像信息的解析效率比文字更高,所以可视化可以使数据更为直观,便于理解,使决策变得高效,所以信息可视化就 ...

  9. 数据科学 IPython 笔记本 7.4 Pandas 对象介绍

    7.4 Pandas 对象介绍 原文:Introducing Pandas Objects 译者:飞龙 协议:CC BY-NC-SA 4.0 本节是<Python 数据科学手册>(Pyth ...

最新文章

  1. 拼接召回在飞猪交通域的实践
  2. Nginx正则表达式之匹配操作符详解
  3. VTK:模型之ExtractLargestIsosurface
  4. Solr 6.7学习笔记(04)-- Suggest
  5. 电脑科学性计算机怎么用,怎么使用科学计算器59 000×(1+r)-2
  6. 【并查集】Supermarket(poj 1456/luogu-UVA1316)
  7. 仿Jquery链式操作的xml操作类
  8. 教你轻松解决苹果Mac安装Axure首次打开报错的问题
  9. 泛函编程(7)-数据结构-List-折叠算法
  10. 主板电源开关接口图解_主板跳线接法示意图,超详细适合DIY新手
  11. abap实现大数据-echar调用
  12. 【历史上的今天】2 月 4 日:Unix 之父诞生;Facebook 上线;微软大洗牌
  13. 如何使用Blender制作360度全景图和全景视频?
  14. 如何从头搭建一个搜索引擎_pylucene,分词,语言编码问题
  15. 判断一个数为奇偶数的三种方法
  16. 浅谈根号分治——暴力的美学
  17. 基于Java Web的在线考试系统的实现
  18. linux 脚本实现物理备份,shell脚本实现系统监视统计与数据备份
  19. 递归树求递归算法时间复杂度
  20. python与脚本语言

热门文章

  1. 解决RK3328 RealTek 8822CS检测不到WIFI模块问题
  2. linux 视频电话,多人音视频通话-Linux开发集成-SDK开发集成-音视频通话-网易云信开发文档...
  3. 传奇GOM引擎登录器生成配置教程
  4. 狂神。Mybatis学习。
  5. (2.1)关系模型之关系结构和约束
  6. 基于weixin-java-tools集成微信小程序支付功能
  7. SAP 公司间销售配置原理和步骤
  8. 计算机无符号是啥,计算机编程中的无符号是什么
  9. python中的数值类型有哪些,Python中数值类型有哪些
  10. 条码软件(Barcode Software)的类别、常用的条码软件、条码扫描软件经验分享