美文网首页
Pandas从入门到精通(6)- 连接

Pandas从入门到精通(6)- 连接

作者: 木头里有虫911 | 来源:发表于2020-12-29 20:49 被阅读0次

    1. 课程内容

    SQL中最常见的操作莫过于将好几张表连接(JOIN)起来查看某些字段,与之类似,Pandas具有功能全面且性能强大连接操作。而且因为我们的DataFrame中有列-columns和索引-index。在Pandas中的连接操作感觉比SQL中要丰富的多。
    本期我们就来串一串这些连接方法,主要有:

    • 关系型连接
      • 针对列进行的merge 方法
      • 针对索引的join方法
    • 方向连接
      • 横向或者纵向拼接-concat方法
      • 其他append/assign方法
        这些方法大部分的参数都类似,实际操作中最常用的是merge和concat
        下面我们将主要精力放在这两个函数上

    1.1 merge

    merge()函数 基本语法:
    pd.merge(df1, df2, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True)
    其中:

    • df1,df2为需要merge的两张表(DataFrame)
    • on - 列(名称)连接,必须在左(df1)和右(df2)DataFrame对象中存在(找到)。
    • left_on - 左侧DataFrame中的列用作键,可以是列名或长度等于DataFrame长度的数组。
    • right_on - 来自右的DataFrame的列作为键,可以是列名或长度等于DataFrame长度的数组。
      left_index - 如果为True,则使用左侧DataFrame中的索引(行标签)作为其连接键。 在具有MultiIndex(分层)的DataFrame的情况下,级别的数量必须与来自右DataFrame的连接键的数量相匹配。
    • right_index - 与右DataFrame的left_index具有相同的用法。
    • sort - 按照字典顺序通过连接键对结果DataFrame进行排序。默认为True,设置为False时,在很多情况下大大提高性能。
    • how - 它是left, right, outer以及inner之中的一个,默认为内inner。 含义分别是左连接 left 、右连接 right 、内连接 inner 、外连接 outer ,它们的区别可以用如下示意图表示:
    image.png

    使用merge时,如果没有指定 on = 哪一列,则默认以重叠列名当做链接键, 当然也可以按照多键连接,只需要'on'参数后传入多键列表即可。

    1.2 join索引连接

    在上面的Merge中,主要是针对columns进行连接,如果在merge中指定on = index, 即按照索引来连接,是否可以呢?答案是可以的。但是这种情况最好直接用join来做。pandas 中利用 join 函数来处理索引连接,它的参数选择要少于 merge ,除了必须的 on 和 how 之外,可以对重复的列指定左右后缀 lsuffix 和 rsuffix 。其中, on 参数指索引名,单层索引时省略参数表示按照当前索引连接。

    1.3 方向连接concat

    前面介绍了关系型连接,其中最重要的参数是 on 和 how ,但有时候用户并不关心以哪一列为键来合并,只是希望把两个表或者多个表按照纵向或者横向拼接,为这种需求, pandas 中提供了 concat 函数来实现。
    在 concat 中,最常用的有三个参数,它们是 axis, join, keys ,分别表示拼接方向,连接形式,以及在新表中指示来自于哪一张旧表的名字。这里需要特别注意, join 和 keys 与之前提到的 join 函数和键的概念没有任何关系。

    在默认状态下的 axis=0 ,表示纵向拼接多个表,常常用于多个样本的拼接;而 axis=1 表示横向拼接多个表,常用于多个字段或特征的拼接。

    1.4 其他连接操作

    其他类似的连接操作还有append,combine等,比较简单,这里不在介绍

    2. 作业练习题

    1:美国疫情数据集

    现有美国4月12日至11月16日的疫情报表,请将 New YorkConfirmed, Deaths, Recovered, Active 合并为一张表,索引为按如下方法生成的日期字符串序列:

    date = pd.date_range('20200412', '20201116').to_series()
    
    In [62]: date = date.dt.month.astype('string').str.zfill(2
       ....:        ) +'-'+ date.dt.day.astype('string'
       ....:        ).str.zfill(2) +'-'+ '2020'
       ....: 
    
    In [63]: date = date.tolist()
    
    In [64]: date[:5]
    Out[64]: ['04-12-2020', '04-13-2020', '04-14-2020', '04-15-2020', '04-16-2020']
    

    解答:
    第一步查看原始数据。原始数据存在一个文件夹中,每个文件是用日期进行命名的csv文件,选择其中一份查看


    image.png
    import pandas as pd
    path = './us_report/'
    file_name = '04-12-2020.csv'
    df = pd.read_csv(path + file_name)
    df.head()
    
    image.png

    第二步:需求分析
    现在需要做两件事:
    1) 将每份csv文件中的New York州的'Confirmed','Deaths','Recovered','Active'数据提取出来
    2)将提取出来的数据合并成一个大的DataFrame, 并且以文件名中的日期作为Index

    第三步:解决思路

    1. 从每份文档中提取信息是一个重复的操作,适合使用一个函数来完成
    2. 这个函数干两件事:提取文件名中的日期和New York州的数据。这个都很简单:
    state = 'New York'
    need_col = ['Confirmed','Deaths','Recovered','Active']
    
    def file_process(f):
        f_index = [f.split('.')[0]] # 注意index必须要是一个列表的形式
        f_path = path + f
        f_df = pd.read_csv(f_path)
        new_df = f_df[f_df['Province_State'] == state][need_col]
        new_df.index = f_index
        
        return new_df
    
    # 使用一个文件调试,看看是否能够正确的提取信息
    file_process('05-01-2020.csv')
    
    image.png

    OK,程序可以跑

    1. 遍历整个文件夹,对每份文件调用相同的函数之后在合并信息,搞定!
    # 读取所有样本
    df1 = file_process('04-12-2020.csv')
    for file in os.listdir(path)[1:]:
        df1 = pd.concat([df1, file_process(file)])
    df1
    

    结果如下:


    image.png

    在这里,使用函数的好处是如果需求有变,例如将New York换成其他州,或者需要其他信息的时候,只要在函数外面定义相应的值即可。由于函数的主体和其他部分是解耦的,当有需求改动的时候,只需要做较小的改动即可完成!

    参考:开源内容Joyful Pandas, 作者 DataWhale耿远昊
    另外,更多精彩内容也可以微信搜索,并关注公众号:‘Python数据科学家之路“ ,期待您的到来和我交流

    相关文章

      网友评论

          本文标题:Pandas从入门到精通(6)- 连接

          本文链接:https://www.haomeiwen.com/subject/bedfoktx.html