此筆記是學習以下兩篇文章以及其他用到過的個人總結
如題,主要分爲數據拼接、數據合併和數據聚合三部分。數據的拼接是指機械地把數據堆到一起,數據的合併是指根據兩個數據的公共屬列合併爲一個數據集,數據聚合是指對數據集進行一些彙總操作,如分組求和或者求平均數等。
-
一、數據拼接
數據連接,大白話就是直接機械地把兩個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)
可以看到經過上述合併,數據貌似變少了,看一下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 操作。
- inner merge:默認的 pandas 行爲,僅保留左側和右側數據框中存在合併 on 值的行;
- left merge:保留左數據框中的每一行。如果右側數據框中存在 on 變量的缺失值,那麼請在結果中添加 NaN 值;
- right merge:保留右數據框中的每一行。如果左側數據框中存在 on 變量的缺失值,那麼請在結果中添加 NaN 值;
- 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)
-
三、數據聚合
- 聚合 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,則各列名爲: