天天看點

資料分析(六)--聚合分組,交叉表,透視表,練習練習一、時間資料操作的補充二、分組聚合三、透視表/交叉表四、項目–員工資訊分析

練習

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進行求和操作

對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]區間内。

解決離差标準化的好處:

  1. 很友善做十分制和百分制的換算
  2. 消除大機關和小機關的影響,消除量綱(量綱:變異大小的差異影響)

薪資資料: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.員工平均工作年限是多少?

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

序列–>數組

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,會報警告。

比如:

原因:

原始資料有八列,這裡将’姓名’、'工齡’兩列排序。

如果使用inplace=True修改原始資料,就相當于剩下的六列沒變化,将排序後的兩列放入,會造成資料混亂。

繼續閱讀