第六章 連接

一、關系型連接

連接:

  • 左連接,右連接=>兩者效果相同,只是列位置不一樣
  • inner(&)outer(||,全連接)

如果出現(xiàn)兩次,則結果為笛卡爾集,即有4個記錄

類型 函數(shù) 參數(shù) 例子 備注
值連接 merge on: 連接的鍵;how:連接方式 df1.merge(df2, on='Name', how='left') 出現(xiàn)重復元素時,需要on的參數(shù)值為多個,使其結果唯一
left_on 和 right_on :指定要連接的列 df1.merge(df2, left_on='df1_name', right_on='df2_name', how='left') 想要連接的列不具備相同的列名
suffixes:指定前綴 df1.merge(df2, on='Name', how='left', suffixes=['_Chinese','_Math']) 兩個表中的列出現(xiàn)了重復的列名
validate:檢查連接的唯一性模式 df1.merge(df2, on=['Class','Name'], how='left',validate='1:m') 共有三種模式,即一對一連接 1:1 ,一對多連接 1:m ,多對一連接 m:1 連接,第一個是指左右表的鍵都是唯一的,后面兩個分別指左表鍵唯一和右表鍵唯一
索引連接 join on: 連接的鍵;how:連接方式 df1.join(df2, how='left')
lsuffix;rsuffix df1.join(df2, how='left', lsuffix='_Chinese', rsuffix='_Math')

練一練

上面以多列為鍵的例子中,錯誤寫法顯然是一種多對多連接,而正確寫法是一對一連接,請修改原表,使得以多列為鍵的正確寫法能夠通過 validate='1:m' 的檢驗,但不能通過 validate='m:1' 的檢驗。

df1 = pd.DataFrame({'Name':['San Zhang', 'San Zhang'],
                    'Age':[20, 21],
                    'Class':['one', 'two']})
df2 = pd.DataFrame({'Name':['San Zhang', 'San Zhang'],
                    'Subject':['Chinese', 'Math'],
                    'Class':['one', 'two']})
df1.merge(df2, on=['Class','Name'], how='left',validate='1:m')
'''
    Name       Age  Class   Subject
0   San Zhang   20  one     Chinese
1   San Zhang   20  one     Math
2   San Zhang   21  two     NaN
'''

二、方向連接

分類 函數(shù) 參數(shù) 例子 備注
合并兩個表 concat axis:拼接方向,axis=0 ,表示縱向拼接多個表,常常用于多個樣本的拼接;而 axis=1 表示橫向拼接多個表,常用于多個字段或特征的拼接; pd.concat([df1, df2])
join:連接形式(inner,outer) pd.concat([df1, df2], axis=1, join='inner') 橫向連接
keys:在新表中指示來自于哪一張舊表的名字 pd.concat([df1, df2], keys=['one', 'two']) 可以通過 keys 參數(shù)產(chǎn)生多級索引進行標記
合并序列和表 append ignore_index=True對新序列對應索引的自動標號 df1.append(s, ignore_index=True) append 中,如果原表是默認整數(shù)序列的索引,那么可以使用 ignore_index=True 對新序列對應索引的自動標號,否則必須對 Series 指定 name屬性。
assign s = pd.Series([80, 90])<br />df1.assign(Grade=s) assign 返回的是一個臨時副本; [xx]會在原表的基礎上進行修改

三、類連接操作

函數(shù) 例子 備注
compare df1.compare(df2) 比較兩個表或者序列的不同處并將其匯總展示;otherself 分別指代傳入的參數(shù)表和被調(diào)用的表自身;值相同則會被填充為缺失值 NaN;想要完整顯示表中所有元素的比較情況,可以設置 keep_shape=True
combine def choose_min(s1, s2):
print('s1', s1)
print('s2',s2)
s2 = s2.reindex_like(s1)
res = s1.where(s1<s2, s2)
res = res.mask(s1.isna()) # isna表示是否為缺失值,返回布爾序列
return res<br />df1.combine(df2, choose_min)
讓兩個表按照一定的規(guī)則進行組合,在進行比較時會自動進行列索引的對齊。傳入函數(shù)的參數(shù)是來自兩個表的同名Series
df1.combine(df2, choose_min, overwrite=False) overwrite=False可以保留 被調(diào)用表 中未出現(xiàn)在傳入的參數(shù)表中的列(例子里df1的A沒有出現(xiàn)在參數(shù)df2的表里),而不會設置未缺失值
combine_first df1 = pd.DataFrame({'A':[1,2], 'B':[3,np.nan]})
df2 = pd.DataFrame({'A':[5,6], 'B':[7,8]}, index=[1,2])
df1.combine_first(df2)
其功能是在對兩張表組合時,若第二張表中的值在第一張表中對應索引位置的值不是缺失狀態(tài),那么就使用第一張表的值填充

練一練

  1. 請在上述代碼的基礎上修改,保留 df2 中4個未被 df1 替換的相應位置原始值。
def choose_min(s1, s2):
    
    s2 = s2.reindex_like(s1)
    res = s1.where(s1<s2, s2) #在Python規(guī)定,np.nan與數(shù)字比較,都會返回False,也就是說它既比任何數(shù)字大,又比任何數(shù)字小。這里表示如果遇到數(shù)字,則會填充數(shù)字
    # res = res.mask(s1.isna()) # isna表示是否為缺失值,返回布爾序列
    return res
df1 = pd.DataFrame({'A':[1,2], 'B':[3,4], 'C':[5,6]})
df2 = pd.DataFrame({'B':[5,6], 'C':[7,8], 'D':[9,10]}, index=[1,2])
df1.combine(df2, choose_min)
'''
    A    B    C     D
0 NaN  NaN  NaN   NaN
1 NaN  4.0  6.0   9.0
2 NaN  6.0  8.0  10.0
'''
  1. 除了 combine 之外, pandas 中還有一個 combine_first 方法,其功能是在對兩張表組合時,若第二張表中的值在第一張表中對應索引位置的值不是缺失狀態(tài),那么就使用第一張表的值填充。下面給出一個例子,請用 combine 函數(shù)完成相同的功能。
def choose_first(s1, s2):
    s2 = s2.reindex_like(s1)
    res = s1.mask(s1.isna(), s2) 
    return res
df1.combine(df2, choose_first)
'''
     A    B
0  1.0  3.0
1  2.0  7.0
2  6.0  8.0
'''

四、練習

Ex1:美國疫情數(shù)據(jù)集

現(xiàn)有美國4月12日至11月16日的疫情報表(在 /data/us_report 文件夾下),請將 New YorkConfirmed, Deaths, Recovered, Active 合并為一張表,索引為按如下方法生成的日期字符串序列:

In [61]: 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']

import os
fileList = os.listdir("../data/us_report")
df = pd.read_csv("../data/us_report/"+fileList[0],usecols=[0,5,6,7,8])
for i in range(1,len(fileList)):
    df = pd.concat([df, pd.read_csv("../data/us_report/"+fileList[i],usecols=[0,5,6,7,8])])
df = df.set_index(['Province_State'])
date = pd.date_range('20200412', '20201116').to_series()
date = date.dt.month.astype('string').str.zfill(2) +'-'+ date.dt.day.astype('string').str.zfill(2) +'-'+ '2020'
date = date.tolist()
df = df.loc['New York']
df['date'] = date
df.reset_index().drop(columns='Province_State').set_index('date')
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容