練習
import pandas as pd
detail = pd.read_excel('detail.xlsx')
print(detail.loc[:,['counts','amounts']].describe())
# 按照菜品名分類
detail['dishes_name'] = detail['dishes_name'].astype('category')
print(detail['dishes_name'].describe())
# count 10037 --10037條數據
# unique 157 --157個菜品
# top 白飯/大碗 --最多的
# freq 323 --top數
# Name: dishes_name, dtype: object
print(detail['dishes_name'].describe().top) # 白飯/大碗
# 按照訂單號分類
detail['order_id'] = detail['order_id'].astype('category')
# print(detail['order_id'])
print(detail[['order_id','dishes_name']].describe())
# order_id dishes_name
# count 10037 10037
# unique 942 157
# top 398 白飯/大碗
# freq 36 323
一、時間數據操作的補充
import pandas as pd
detail = pd.read_excel('detail.xlsx')
detail['place_order_time'] = pd.to_datetime(detail['place_order_time'])
years = [i.year for i in detail['place_order_time']]
print(years) # 列表
print(detail['place_order_time'].dt.year) # 序列
二、分組聚合
import pandas as pd
import numpy as np
detail = pd.read_excel('data/meal_order_detail.xlsx')
(一)分組
groupby()
result = detail[['order_id','counts','amounts']].groupby(by='order_id')
# print(result) # <pandas.core.groupby.DataFrameGroupBy object at 0x0000000006243978>
# print(result['counts']) # <pandas.core.groupby.SeriesGroupBy object at 0x0000000006184E48>
可進行分組,但分組後的所有列,只能使用相同的聚合函數操作。
如果想讓不同列進行不同的聚合操作,就只能編寫多次,分別操作。
# 分組後,每個訂單平均點了多少份菜和菜的均價
print(result.mean())
print(result[['counts','amounts']].mean())
# 分組後,每個訂單點菜數和銷售總額
print(result.sum())
# 分組後,每組中的數據條數
print(result.size())
(二)聚合
1.agg()/aggregate()
**def aggregate(self, func, axis=0, *args, ****kwargs):
不同列可進行不同的聚合操作。
(1)用法1
對counts和amounts進行求和操作
print(detail[['counts','amounts']].agg(np.sum))
對counts進行求和操作,對amounts進行均值操作
func接收多個函數名,使用列表將多個函數名封裝起來。
print(detail[['counts','amounts']].agg([np.sum,np.mean]))
# counts amounts
# sum 11126.000000 449872.000000
# mean 1.108499 44.821361
(2)用法2
print(detail.agg({'counts':np.sum,'amounts':np.mean}))
# counts 11126.000000
# amounts 44.821361
# dtype: float64
print(detail.agg({'counts':np.sum,'amounts':[np.sum,np.mean]}))
# counts amounts
# mean NaN 44.821361
# sum 11126.0 449872.000000
(3)自定義統計函數
銷量*2
def double_sum(data):
return np.sum(data)*2
print(detail.agg({'counts':double_sum}))
(4)在分組的基礎上進行聚合函數
格式:DataFrameGroupBy.聚合函數
result = detail[['order_id','counts','amounts']].groupby(by='order_id')
print(result.agg({'counts':np.sum,'amounts':[np.sum,np.mean]}))
2.apply()
**def apply(self, func, axis=0, broadcast=False, raw=False, reduce=None,args=(), ****kwds):
detail[[‘counts’,‘amounts’]]–DataFrame
detail[‘counts’]–Series
可以對DataFrame操作,也可以對Series進行操作。
print(detail[['counts','amounts']].apply(np.mean))
print(result.apply(np.mean))
apply和agg的區別
apply是對整個表格中的數據進行整合;agg可以讓不同的字段執行不同的聚合函數。
(三)解決離差標準化問題
1.離差標準化
本質:就是對原始數據進行線性變換。
特點:通過離差標準化的計算後,計算的值將落在[0,1]區間內。
解決離差標準化的好處:
- 很方便做十分制和百分制的換算
- 消除大單位和小單位的影響,消除量綱(量綱:變異大小的差異影響)
例
薪資數據:5000,6000,8000,10000,15000
第一組(以元爲單位):
5000,6000,8000,10000,15000
第二組(以k爲單位):
5,6,8,10,15
對這兩組數據計算方差/標準差,以表示數據的離散程度。
顯然第一組數據要比第二組數據的標準差大得多,也就是更加離散。
2.計算
公式:new_X = (X-min)/(max-min)
值域:[0,1]
3.使用transform(),解決利差標準化
counts_min = detail['counts'].min()
counts_max = detail['counts'].max()
print(detail['counts'].transform(lambda x:(x-counts_min)/(counts_max-counts_min)))
amounts_min = detail['amounts'].min()
amounts_max = detail['amounts'].max()
print(detail['amounts'].transform(lambda x:(x-amounts_min)/(amounts_max-amounts_min)))
解決前後的標準差對比
print(detail['amounts'].std()) # 36.80855003545274
amounts_min = detail['amounts'].min()
amounts_max = detail['amounts'].max()
detail['amounts_std'] = (detail['amounts']-amounts_min)/(amounts_max-amounts_min)
print(detail['amounts_std'].std()) # 0.2079579098048175
三、透視表/交叉表
(一)透視表
pivot_table()
def pivot_table(data, values=None, index=None, columns=None, aggfunc=‘mean’,fill_value=None, margins=False, dropna=True,margins_name=‘All’):
aggfunc–聚合函數名,不指定時,默認使用mean求平均
detail_pivot1 = pd.pivot_table(detail[['order_id','counts','amounts']],index='order_id')
print(detail_pivot1)
detail_pivot2 = pd.pivot_table(detail[['order_id','counts','amounts']],index='order_id',aggfunc=np.sum)
detail_pivot2 = pd.pivot_table(detail[['order_id','counts','amounts']],index='order_id',aggfunc='sum')
print(detail_pivot2)
(二)交叉表
crosstab()
index參數不能跟字段名,要跟字段值。
result = pd.crosstab(index=detail['order_id'],columns=detail['dishes_name'],values=detail['counts'],aggfunc=np.sum)
print(result)
四、項目–員工信息分析
import pandas as pd
import numpy as np
data = pd.read_excel('英雄聯盟員工信息表.xlsx')
1.表中有些員工數據是重複的,通過選取合適的字段對整個表進行去重
當工號與名字一樣時認爲該數據爲重複
print('原始:\n',data.shape)
# inplace=True--無返回值
# inplace=False--有返回值
data.drop_duplicates(subset=['姓名','工號'],inplace=True)
print('去重後:\n',data.shape)
2.員工平均工作年限是多少?
print(data['工齡'].mean())
3.公司任職最久的三名員工分別是誰?
對一個序列進行排序
sort_values()
def sort_values(self, by, axis=0, ascending=True, inplace=False,kind=‘quicksort’, na_position=‘last’):
ascending–默認True,升序;False爲降序
# results = data['工齡'].sort_values(by='工齡') # 會報錯
result = data[['姓名','工齡']].sort_values(by='工齡',ascending=False,inplace=False)
print(result.head(3))
4.員工總體流失率是多少?
values
序列–>數組
print(data['姓名'])# print(data['姓名'].values)
data[‘狀態’] == ‘離職’ – 廣播
mask = data['狀態']=='離職'
print(data.iloc[mask,:])
num = data.iloc[mask.values,:].shape[0]
print('離職率:',num/data.shape[0])
還可簡化爲
num = mask.values.sum()
print('離職率:',num/data.shape[0])
5.各部門有多少名員工?
result = data[['部門','姓名']].groupby(by='部門').count()
print(result)
問題
有時inplace=True,會報警告。
比如:
data[['姓名','工齡']].sort_values(by='工齡',ascending=False,inplace=True)
原因:
原始數據有八列,這裏將’姓名’、'工齡’兩列排序。
如果使用inplace=True修改原始數據,就相當於剩下的六列沒變化,將排序後的兩列放入,會造成數據混亂。