请选择 进入手机版 | 继续访问电脑版

pandas-task06-连接.md

[复制链接]
太阳神鹰 发表于 2021-1-1 17:46:33 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
文章目次



一、关系型毗连

1. 毗连的根本概念

对DataFrame或命名的Series对象,按照毗连,和数据库的毗连根本一致一样,同样也有左连和右连。重复数据按照笛卡尔积举行毗连。
2. 值毗连 merge

上面说的按照键毗连也是一种值毗连,除了按照一列值举行毗连外还能按照多列值的组合举行毗连。使用merge实现。
看下pandas文档里怎么说的
DataFrame.merge(right, how=‘inner’, 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)

  • 此中DataFrame和right分别对应上述的表一和表二,毗连的必须是dataframe或命名Series.
  • how体现毗连方式,有{‘left’, ‘right’, ‘outer’, ‘inner’, ‘cross’}这几种, 默认‘inner’即内联。
    left左连,right右连上面已经说明,即以哪个表为主。
    inner内连体现取两个表对应属性的交集,outer取并集。
    cross代表取两个表对应键的笛卡尔积,保存左表的顺序。
  • on:要参加的列或列构成的list。必须在两个DataFrame中都可以找到它们。如果on为None且未在索引上归并,则默认为两个DataFrame中列的交集。
  1. df1 = pd.DataFrame({'Name':['San Zhang','Si Li'],                        'Age':[20,30]})df2 = pd.DataFrame({'Name':['Si Li','Wu Wang'],                        'Gender':['F','M']})print(df1.merge(df2, on='Name', how='left').to_markdown())
复制代码
表一
NameAge0San Zhang201Si Li30表二
NameGender0Si LiF1Wu WangM表一和表二按照姓名举行左连之后
NameAgeGender0San Zhang20nan1Si Li30F​所谓左连右连,即毗连的时候键按照哪个表为主,例子中表一表二举行左连即表一为主,按表一的所有姓名去对应表二中的姓名举行毗连,并把表二中对应的其他属性(gender性别)附上。右连同理。
4. left_on和right_on 指明左右毗连的列或索引,适用于两个表中想要毗连的列不具备相同的列名的时候。可以为列名大概list。


  • left_index和right_index和上面一样是为了毗连差别的索引相同但是索引名称差别的时候指定左右索引名字。
  • sort是否对效果举行排序,默认不排序,即按照how中的效果顺序。这里试了下如果sort=True是对毗连的那列(或多列)按照字母表顺序举行排序
  • suffixes 后缀,当归并后其他属性值一样,用于区分,如果不指定则默认加上_x 和 _y。
    注意使用后缀的前提当前归并的列/索引的名称一样
比如下面归并张三的语文和数学结果,这俩结果在两个老师的记分册中都叫得分,统计张三的所有结果时,为了区别我们给他们分别加上对应的学科名称后缀,语文第一次挂科了举行了补考所以有两次结果,也加上后缀区别。
  1. df1 = pd.DataFrame({'Name':['San Zhang'],'Grade':[50]})df2 = pd.DataFrame({'Name':['San Zhang'],'Grade':[80]})df3 = pd.DataFrame({'Name':['San Zhang'],'Grade_Chinese':[90]})res1=df1.merge(df2, on='Name', how='left', suffixes=['_Chinese','_Math'])res1.merge(df3, on='Name', how='left', suffixes=['_1','_2'])
复制代码
NameGrade_Chinese_1Grade_MathGrade_Chinese_20San Zhang508090

  • validate(可选)查抄对应模式,查抄的是当前列属性是否是A表和B表一对一(“one_to_one” or “1:1”)、一对多(“one_to_many” or “1:m”)、多对一(“many_to_one” or “m:1”)大概多对多 (“many_to_many”)的关系。
    测试:
    这部份测试没有生效,不返回True或False,开始以为是pandas版本低没有升级的原因,反面升级成最1.1.0版本依旧如此。经过和群里小同伴讨论后明确了,当查抄不报错时体现通过,不通过会报错。之前我比力的是多列作为毗连条件,情况许多,下面单独说明。
    查抄单列情况时,可以正确查抄出。

    查抄多列是都都满足时,效果不对,比如下面Name很明显时多对多关系,但是这里1:m没有报错。所以validate不适用于多列的查抄。

    还有一点需要说明
    事实上validate的’‘1:m’'中的’1’是强约束 , 'm’是弱约束
    '1’限制on选中的列必须是unique的值
    'm’则不限制 , 既可以unique也可以非unique
    因此 , validate=‘m:m’ 就可以全员通过和没设置一样 , 只有’1’有限制效果
练一练

上面以多列为键的例子中,错误写法显然是一种多对多毗连,而正确写法是一对一毗连,请修改原表,使得以多列为键的正确写法可以大概通过 validate=‘1:m’ 的查验,但不能通过 validate=‘m:1’ 的查验。
  1. df1 = pd.DataFrame({'Name':['San Zhang', 'Si Li'],                        'Age':[20, 21],                        'Class':['one', 'two']})df2 = pd.DataFrame({'Name':['San Zhang', 'San Zhang'],                        'Gender':['F', 'M'],                        'Class':['two', 'one']})df1.merge(df2, on='Name', how='left',validate='m:1')
复制代码
将表1中重复的名字张三改为李四,这样表一姓名都为唯一,表二有两个张三,满足姓名1:m,不满足m:1,符合条件。
3. 索引毗连

所谓索引毗连,就是把索引看成键,因此这和值毗连本质上没有区别, pandas 中使用 join 函数来处置惩罚索引毗连,它的参数选择要少于 merge ,除了必须的 on 和 how 之外,可以对重复的列指定左右后缀 lsuffix 和 rsuffix 。此中, on 参数指索引名,单层索引时省略参数体现按照当前索引毗连。
疑惑:Merge也可以通过索引举行毗连,那么Merge和Join两个毗连的有区别吗,下面实践了一下。

分别通过Merge和Join得到效果:

可以看到,效果完全一致,通过和群里小同伴互换,我知道了merge包罗了join操作,支持两个df间行方向或列方向的拼接操作,默认列拼接,取交集,而join只是简化了merge的行拼接的操作。
二、方向毗连

1. concat

前面的是细致的毗连,但有时候用户只需要两个表大概多个表按照纵向大概横向拼接,为这种需求, pandas 中提供了 concat 函数来实现。
在 concat 中,最常用的有三个参数,它们是 axis, join, keys ,分别体现拼接方向,毗连形式,以及在新表中指示来自于哪一张旧表的名字。这里需要特别注意, join 和 keys 与之前提到的 join 函数和键的概念没有任何关系。
在默认状态下的 axis=0 ,体现纵向拼接多个表,经常用于多个样本的拼接;而 axis=1 体现横向拼接多个表,常用于多个字段或特征的拼接。
纵向拼接:
  1. df1 = pd.DataFrame({'Name':['San Zhang','Si Li'],                        'Age':[20,30]})df2 = pd.DataFrame({'Name':['Wu Wang'], 'Age':[40]})pd.concat([df1, df2],0)
复制代码
NameAge0San Zhang201Si Li300Wu Wang40横向拼接:
  1. pd.concat([df1, df2],1)
复制代码
NameAgeNameAge0San Zhang20Wu Wang401Si Li30nannan虽然说 concat 不是处置惩罚关系型归并的函数,但是它仍然是关于索引举行毗连的。纵向拼接会根据列索引对其,默认状态下 join=outer ,体现保存所有的列,并将不存在的值设为缺失; join=inner ,体现保存两个表都出现过的列。横向拼接则根据行索引对齐, join 参数可以类似设置。
​因此,当确认要使用多表直接的方向归并时,尤其是横向的归并,可以先用 reset_index 方法恢复默认整数索引再举行归并,防止出现由索引的误对齐和重复索引的笛卡尔积带来的错误效果。
最后, keys 参数的使用场景在于多个表归并后,用户仍然想要知道新表中的数据来自于哪个原表,这时可以通过 keys 参数产生多级索引举行标志。例如,第一个表中都是一班的同学,而第二个表中都是二班的同学,可以使用如下方式归并:
  1. df1 = pd.DataFrame({'Name':['San Zhang','Si Li'],                    'Age':[20,30]})df2 = pd.DataFrame({'Name':['Wu Wang'], 'Gender':['M']})pd.concat([df1, df2],axis=1,join='outer',keys=['1','2'])
复制代码

2. 序列Series与表DataFrame的归并

append 和 assign(分配)操作
在 append 中,如果原表是默认整数序列的索引,那么可以使用 ignore_index=True 对新序列对应的索引自动标号,否则必须对 Series 指定 name 属性。
  1. df1 = pd.DataFrame({'Name':['San Zhang','Si Li'],                    'Age':[20,30]})s = pd.Series(['Wu Wang', 21], index = df1.columns)df1.append(s, ignore_index=True)
复制代码
NameAge0San Zhang201Si Li302Wu Wang21对于 assign分配 而言,虽然可以使用其添加新的列,但一般通过 df[‘new_col’] = … 的形式就可以等价地添加新列。同时,使用 [] 修改的缺点是它会直接在原表上举行改动,而 assign 返回的是一个临时副本:

append和assign的区别
append是不改变原有表格结构,增加一条数据。
assign是增加一个新的列。
三、类毗连操作

除了上述先容的若干毗连函数之外, pandas 中还设计了一些函数可以大概对两个表举行某些操作,这里把它们统称为类毗连操作。
1. 比力

它可以大概比力两个表大概序列的差别处并将其汇总展示
  1. df1 = pd.DataFrame({'Name':['San Zhang', 'Si Li', 'Wu Wang'],                            'Age':[20, 21 ,21],                            'Class':['one', 'two', 'three']})df2 = pd.DataFrame({'Name':['San Zhang', 'Li Si', 'Wu Wang'],                            'Age':[20, 21 ,21],                            'Class':['one', 'two', 'Three']})df1.compare(df2)
复制代码
(‘Name’, ‘self’)(‘Name’, ‘other’)(‘Class’, ‘self’)(‘Class’, ‘other’)1Si LiLi Sinannan2nannanthreeThree效果中返回了差别值所在的行列,如果相同则会被填充为缺失值 NaN ,此中 other 和 self 分别指代传入的参数表和被调用的表自身。
如果想要完整显示表中所有元素的比力情况,可以设置 keep_shape=True ,效果如下:

2. 组合

combine 函数可以大概让两张表按照一定的规则举行组合,在举行规则比力时会自动举行列索引的对齐。对于传入的函数而言,每一次操作中输入的参数是来自两个表的同名 Series ,依次传入的列是两个表列名的并集,例如下面这个例子会依次传入 A,B,C,D 四组序列,每组为左右表的两个序列。同时,举行 A 列比力的时候, s2 指代的就是一个全空的序列,因为它在被调用的表中并不存在,而且来自第一个表的序列索引会被 reindex 成两个索引的并集。详细的过程可以通过在传入的函数中插入适当的 print 方法查看。
[code]def choose_min(s1, s2):        s2 = s2.reindex_like(s1)        # 当不满足s1
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )