Pandas向量化函数-分组相关-透视表

一、向量化函数

向量化函数是指将输入参数为向量的函数,通过对向量进行操作,得到输出为向量的函数。在数学和计算机科学领域中,向量化函数通常用于加速计算和提高代码的可读性。

1.向量化函数展示

import pandas as pd
import numpy as np
df=pd.DataFrame({'a':[10,20,30],'b':[20,30,40]})
df
def avg_1(x,y):
    return (x+y)/2
avg_1(df['a'],df.b)

def avg_2(x,y):
    #如果x列传入20,就返回空
    if x==20: #此处报错,x是向量,20是标量,他们无法做判断
        return np.NaN
    return (x+y)/2
avg_2(df['a'],df.b)

此处报错原因其实就是向量和标量之间无法比较,需要通过以下向量化函数解决该问题,

方法一:np.vectorize(要被向量化的函数)

# 6. 使用 np.vectorize 将函数向量化.
# 写法1: 通过 np.vectorize(要被向量化的函数名) 方式实现.
avg_2_mod_vec = np.vectorize(avg_2_mod)
avg_2_mod_vec(df['a'], df['b'])

方法二:装饰器方式,即在那个有问题的函数的上一行@np.vectorize即可

#方法二: 通过装饰器方式实现,再要被向量化函数的上加上@np.vectorize
@np.vectorize
def avg_3(x,y):
    #如果x列传入20,就返回空
    if x==20: #此处报错,x是向量,20是标量,他们无法做判断
        return np.NaN
    return (x+y)/2
avg_3(df['a'],df.b)

2.lambda表达式

当函数比较简单的时候, 就没有必要创建一个def 一个函数, 可以使用lambda表达式创建匿名函数,格式:    lambda 形参列表 :函数体

# 基于上面已经创建好的df对象继续操作
# 原始方法:
def my_fun(x):
    return x+1
df.apply(my_fun)
# lambda表达式:
df.apply(lambda x : x+1) # 效果同上
df.apply(lambda x : x**2)

# 统计每列非空值数量
# x表示1个Series对象
df.apply(lambda x :x.isnull().count())
# df对象的函数
df.isnull().count()

 二、数据分组

python中的分组groupby()类似于SQL中的group by 分组字段,按照不同取值进行分组。

一、分组+聚合

1.首先导入gapminder数据

import pandas as pd
import numpy as np
df=pd.read_csv('./gapminder.tsv',sep='\t')
df

简单看下数据

2.需求:统计不同年份平均年龄

df.groupby('year').lifeExp.mean()

3.需求:统计不同大洲平均年龄

# 这里给大家提供多种写法
# 1.标准写法中括号
df.groupby('continent')['lifeExp'].mean()
# 2.df.列名
df.groupby('continent').lifeExp.mean()
# 2.结合agg()或aggregate()函数实现,完全一样
df.groupby('continent').lifeExp.agg('mean')#这个mean时numpy里的,需要加''包裹
df.groupby('continent').lifeExp.aggregate('mean')
# 3.上述格式变形写法,{要操作的列1:聚合函数1,.....}
df.groupby('continent').agg({'lifeExp':'mean'})
# 4.直接传入numpy包下的函数
df.groupby('continent').lifeExp.agg(np.mean)
df.groupby('continent').agg({'lifeExp':np.mean})

也可以通过自定义函数的方式,但不推荐在这里使用,这个需求用一句简单的代码就可以搞定喽

# 5.传入自定义函数,计算平均值
def my_mean(col):
    return col.mean()
df.groupby('continent').lifeExp.agg(my_mean)
df.groupby('continent').agg({'lifeExp':my_mean})

但是下面这个需求,可以用用它

4.计算全球平均寿命的平均值和分组之后平均值的差值

# 根据年份分组计算每年平均寿命,用每年平均寿命-平均寿命列的平均值
def my_mean_diff(col,global_value):
    """
    :param col: 某年所有的平均寿命值
    :param global_value: 全球平均寿命
    :return: 
    """
    return my_mean(col)-global_value
# df.lifeExp.mean()
# df.groupby('year').lifeExp.mean()
df.groupby('year').lifeExp.agg(my_mean_diff,global_value=df.lifeExp.mean())

二、分组+转换

这里需要用到transform()函数,需要把DataFrame中的值传递给一个函数, 而后由该函数"转换"数据,它与不同聚合不同的是,不会减少数据量。

来个小案例,用transform填充缺失值

import pandas as pd
import numpy as np
tips=pd.read_csv('dataset04/tips.csv')
tips
# 随机抽10条数据,random_state表示随机种子,每次抽到的结果都是一样的
tips10=tips.sample(10,random_state=6)
tips10
#np.random.permutation(字段)根据传入的内容进行随机打乱顺序
tips10.loc[np.random.permutation(tips10.index)[:4],'total_bill']=np.NaN
tips10
# 查看缺失值
tips10.groupby('sex').count()
# 自定义函数用每组平均值填充每组缺失值
def my_fill_na(col):
    return col.fillna(col.mean())
tips10.groupby('sex').total_bill.transform(my_fill_na)

三、分组+过滤

还是基于tips数据,调用filter 方法,传入一个返回布尔值的函数,返回False的数据会被过滤掉

# 需求: 根据就餐人数进行分组, 过滤掉条目数少于30条的组
# 1. 使用小费数据
tips = pd.read_csv('data/tips.csv')
# 2. 查看用餐人数
tips['size'].value_counts()
# 3. 人数为1、5和6人的数据比较少,考虑将这部分数据过滤掉
tips_filtered = tips.groupby('size').filter(lambda x: x['size'].count() > 30)
# 4. 查看结果
tips_filtered['size'].value_counts()
# 5. 合并版写法
tips.groupby('size').filter(lambda x: x['size'].count() > 30)['size'].value_counts()

三、透视表

1.不利用透视表解决需求,使用会员信息查询数据集举例

# 导入数据
import pandas as pd
custom_info=pd.read_excel('dataset04/会员信息查询.xlsx')
custom_info

from datetime import datetime
# 1.原数据中没有年月字段,要将日期列转为年月字段加入到df对象中
# custom_info[]=custom_info['注册时间'].apply(lambda x:x.strftime('%Y-%m'))
custom_info.loc[:,'注册年月']=custom_info['注册时间'].apply(lambda x:x.strftime('%Y-%m'))
custom_info
# 2.计算每月的会员月增量
custom_info[['会员卡号','会员等级','会员来源','注册年月']]
month_count=custom_info.groupby('注册年月')[['会员卡号']].count()
month_count.columns=['月增量']
month_count

2.利用透视表解决需求

首先了解以下透视表pivot_table,它有四个重要参数:

(1)values: 要做聚合操作的列名

(2)index: 行索引, 传入原始数据的列名, 这一列中每个取值会作为透视表结果的1个行索引.

(3)columns: 列索引, 传入原始数据的列名, 这一列中每个取值会作为透视表结果的1列.

(4) aggfunc: 聚合函数

# 增量会员等级分布
member_rating=custom_info.pivot_table(index='注册年月',columns='会员等级',values='会员卡号',aggfunc='count')
member_rating=member_rating[1:]

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值