数据分析(六)--聚合分组,交叉表,透视表,练习

练习

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]区间内。

解决离差标准化的好处

  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.员工平均工作年限是多少?

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修改原始数据,就相当于剩下的六列没变化,将排序后的两列放入,会造成数据混乱。

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