pandas學習(三):數據拼接、數據合併和數據聚合

此筆記是學習以下兩篇文章以及其他用到過的個人總結

如題,主要分爲數據拼接、數據合併和數據聚合三部分。數據的拼接是指機械地把數據堆到一起,數據的合併是指根據兩個數據的公共屬列合併爲一個數據集,數據聚合是指對數據集進行一些彙總操作,如分組求和或者求平均數等。 


  • 一、數據拼接

數據連接,大白話就是直接機械地把兩個dataframe橫着拼起來(按行連接)或者豎着連起來(按列連起來)

  • 按行連接

# -*- coding: utf-8 -*-
__author__ = 'fff_zrx'
import pandas as pd
dd = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
        'year': [2000, 2001, 2002, 2001, 2002],
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
df = pd.DataFrame(dd, columns=['year', 'state', 'pop'])
print(df)
df1=df
data=pd.concat([df,df1])
#  重設從0開始的索引
data = data.reset_index(drop=True)
print(data)

 

data=df.append(df1)

利用append一樣可以實現同樣的效果 

  • 按列連接

將上面的代碼換一行即可,給axis賦值爲1,默認是0

data=pd.concat([df,df1],axis=1)
  • 二、數據合併

數據合併,是指利用兩個數據的公共屬列,將兩個數據集合併爲一個數據集。

info_stu = {'name': ['aa', 'bb', 'cc', 'dd', 'ee','ff'],
        'age': [12, 13, 14, 15, 16,17],
        'id': [111, 122, 125, 150, 160,177]
            }
info_score={"id":[111, 122, 125, 150, 160,179],
            "Math":[77,66,88,99,100,55],
            "Chinese":[75,76,77,78,79,66],
            "English":[74,75,76,77,78,67]
            }

df1 = pd.DataFrame(info_stu)
df2 = pd.DataFrame(info_score)
測試數據

 

result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id')
print(result)
在這裏插入圖片描述
函數參數示意圖,來自chen_h的博客

 

可以看到經過上述合併,數據貌似變少了,看一下shape

print("info_stu: {}".format(df1.shape))
print("info_score: {}".format(df2[['id', 'Math', 'Chinese']].shape))
print("result dimensions: {}".format(result.shape))
print(df1['id'].isin(df2['id']).value_counts())

結果的數目正是兩個df中均存在id的數目 

默認情況下,在 pandas 中僅保留左右dataframe之間的公共值,即使用了內部(inner)合併

以下表述摘自:chen_h的博客

pandas 中有三種不同類型的合併。這些合併類型在大多數數據庫和麪向數據的語言(SQL,R,SAS)中都很常見,通常稱爲 join 操作。

  1. inner merge:默認的 pandas 行爲,僅保留左側和右側數據框中存在合併 on 值的行;
  2. left merge:保留左數據框中的每一行。如果右側數據框中存在 on 變量的缺失值,那麼請在結果中添加 NaN 值;
  3. right merge:保留右數據框中的每一行。如果左側數據框中存在 on 變量的缺失值,那麼請在結果中添加 NaN 值;
  4. outer merge:完全外部連接返回左側數據框中的所有行,右側數據框中的所有行,並在可能的情況下匹配行,其他地方使用 NaN 值;

在這裏插入圖片描述

  •  左合併

result 數據框的頂部包含成功匹配的項,而底部包含 df2 中的 id 在df1中沒有相應id 的行。

df1 = pd.DataFrame(info_stu)
df2 = pd.DataFrame(info_score)

result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id',
                  how="left")
print(result)
print("info_stu: {}".format(df1.shape))
print("info_score: {}".format(df2[['id', 'Math', 'Chinese']].shape))
print("result dimensions: {}".format(result.shape))
print(print("There are {} missing values in the result.".format(result['Math'].isnull().sum())))

因爲在df1裏面有個id,177,在df2裏沒有對應的

  • 右合併
result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id',
                  how="right")
print(result)
print("info_stu: {}".format(df1.shape))
print("info_score: {}".format(df2[['id', 'Math', 'Chinese']].shape))
print("result dimensions: {}".format(result.shape))
print("There are {} missing values in the result.".format(result['name'].isnull().sum()))

因爲df2裏有個id,179,在df1裏沒有對應的

  •  外部合併

外連接可以看做是左連接和右連接的組合,或者是內連接的相反。在外部連接中,左側和右側數據框中的每一行都會保留在結果中,其中 NaN 爲沒有匹配到的變量。

result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id',
                  how="outer")
print(result)
print("info_stu: {}".format(df1.shape))
print("info_score: {}".format(df2[['id', 'Math', 'Chinese']].shape))
print("result dimensions: {}".format(result.shape))

爲了幫助識別行的來源,pandas 提供了一個指標參數,可以與 merge 函數一起使用,該函數在輸出中創建一個名爲 _merge 的附加列,用於標記每行的原始源。 

result = pd.merge(df1,
                 df2[['id', 'Math', 'Chinese']],
                 on='id',
                  how="outer",
                  indicator=True)

合併運算符中使用的列不需要在左側和右側數據幀中命名相同。若相同,使用on參數即可,若不同,則需要使用 left_on 和 right_on 參數。

# -*- coding: utf-8 -*-
__author__ = 'fff_zrx'
import pandas as pd
info_stu = {'name': ['aa', 'bb', 'cc', 'dd', 'ee','ff'],
        'age': [12, 13, 14, 15, 16,17],
        'id1': [111, 122, 125, 150, 160,177]
            }
info_score={"id2":[111, 122, 125, 150, 160,179],
            "Math":[77,66,88,99,100,55],
            "Chinese":[75,76,77,78,79,66],
            "English":[74,75,76,77,78,67]
            }

df1 = pd.DataFrame(info_stu)
df2 = pd.DataFrame(info_score)

result = pd.merge(df1,
                 df2[['id2', 'Math', 'Chinese']],
                 left_on='id1',
                 right_on='id2',
                  how="outer",
                  indicator=True)
print(result)
  • 三、數據聚合 

詳見pandas系列學習(六):數據聚合

  • 聚合 DataFrame

pandas 可以計算不同的統計數據。例如,計算列的平均值,最大值,最小值,標準偏差等。

print(data['item'].count())
print(data['duration'].min())
print(data['duration'].max())
print(data['duration'].mean())
print(data[data['item'] == 'call']['duration'].sum())
print(data['month'].value_counts())
print(data['network'].nunique())
  • 分組聚合DataFrame

groupby() 函數將返回 GroupBy 對象,它描述瞭如何拆分原始數據集的行。

GroupBy 對象.groups變量是一個字典,其鍵是計算的唯一組,對應的值是屬於每個組的軸標籤

data = pd.read_csv('./phone_data.csv')
data['date'] = data['date'].apply(dateutil.parser.parse, dayfirst=True)
d=data.groupby(['month']).groups
print(type(d))
print(data.groupby(['month']).groups.keys())
for key,values in d.items():
    print(key)
    print(values)

 

按單列分組: 

print(data.groupby('month')['duration'].sum())
print(data.groupby('month')[['duration']].sum())

 第一行返回結果是Series格式 ,第二行結果是DataFrame格式

print(data.groupby('month')[['duration']].sum())
print(data.groupby('month',as_index=False)[['duration']].sum())

 Groupby 輸出將默認把你選擇的分組列設置爲索引,要避免設置此索引,請將 as_index=False 傳遞給 groupby 函數

 

按多列分組:

print(data.groupby(['month', 'item'])['date'].count())

將單個函數應用於組中的列:

s1=data.groupby(['month', 'item'],as_index=False).agg({'duration':"sum",
                                     'network_type': "count",
                                     'date': lambda x:max(x)-min(x)})
#列命名需單獨完成
s1.columns=['month','item','sum of dur','num of net','num of day']
print(s1)

 

agg中傳入字典,字典的key是列名,value是對該列進行聚合的函數,支持匿名函數。

所以這個字典也可以提前定義再傳入 ,下面代碼作用等同於上面

aggs={'duration':"sum",'network_type': "count",'date': lambda x:max(x)-min(x)}
s1=data.groupby(['month', 'item'],as_index=False).agg(aggs)
  •  將多個函數應用於組中的列
s2=data.groupby(['month', "item"],as_index=False).agg({'duration': ["min", "max", "sum"],
                                     'network_type': "count",
                                     'date': ["min", 'first', 'nunique']})

 

在列上計算多個統計信息時,結果數據框將在列軸中設置多個索引。這可能很難處理,必須在 groupby 操作後重命名列。

grouped = data.groupby('month',as_index=False).agg({"duration": ["min","max","mean"]})
print(grouped)
grouped.columns = grouped.columns.droplevel(level=1)
print(grouped)
print(grouped.columns)
grouped.columns=['month',"min_duration","max_duration","mean_duration"]
print(grouped)

關鍵操作是這句,把列上的多級索引刪去了,

grouped.columns = grouped.columns.droplevel(level=1)

 執行後各列名爲:

如果level設置爲0,則各列名爲:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章