pandas—apply

某段代码多次被使用,且少量修改—使用函数

'''简单创建函数'''
#求2数的平均值
def avg_2(x,y):
    s = (x+y)/2
    return s
#调用
print(avg_2(4,193))
#98.5

1 使用函数

'''使用函数'''
import pandas as pd
#创建一个DataFrame
df = pd.DataFrame({'a':[24,57,23,52],
                   'b':[24,42,52,36],
                   'c':[12,48,10,72]})
print(df)

#调用求平均值的函数,计算a列和b列 的平均值
print(avg_2(df['a'],df['b']))
#简单的例子情况下也可以不调用函数实现
#print((df['a']+df['b'])/2)
'''
0    24.0
1    49.5
2    37.5
3    44.0
'''

1.1 Series的apply方法

从DataFrame中取一列返回的对象类型是Series

Series有一个apply方法,该方法有个func函数,当传递给他一个函数后,apply方法会把传入的函数应用到Series的每个元素。

注意:使用时调用的函数avg_2后面不需要再加()

#用于传递一个参数,比如求平方和
sq = df['a'].apply(avg_2)   
print(sq)

#当有两个参数时,给y指定具体值,适用求幂次方或几次方
sq = df['a'].apply(avg_2,y=6)   #求a列与y=6的平均值
print(sq)
'''
0    15.0
1    31.5
2    14.5
3    29.0
'''

1.2 DataFrame的apply方法

'''写一个函数,输出自己'''
def print_me(x):
    print(x)
#默认按列进行输出,axis=1设置成按行输出
df.apply(print_me,axis=0)  #将df按列一个个输出
df.apply(print_me,axis=1)
#有两个参数时,需要为每个参数都有传入值
#对求均值的函数修改
def avg_2_apply(row):
    x=row[0]
    y=row[1]
    return (x+y)/2

print(df.apply(avg_2_apply))          #行其实是列,此时是前两行求均值
print(df.apply(avg_2_apply,axis=1))   #前两列求均值

2 apply高级用法

#seaborn库内置titanic数据集
import seaborn as sns
titanic = sns.load_dataset("titanic")
#查看数据集基本特征
print(titanic.info())

'''写函数'''
#缺失值数目
import numpy as np
def count_missing(vec):
    null_vec=pd.isnull(vec)      #根据是否为缺失值组成一个向量
    null_count=np.sum(null_vec)  #计算null值个数  (null值对应true,true为1)
    return null_count

#缺失值占比
def prop_missing(vec):
    num = count_missing(vec)    #获得缺失值数目
    dem = vec.size              #获得向量中元素个数
    return num/dem

#完整值所占比例
def prop_complete(vec):
    return 1-prop_missing(vec)  #1减去缺失值占比

2.1 按列应用

#应用于各列
cmis_col = titanic.apply(count_missing)
pmis_col = titanic.apply(prop_missing)
pcom_col = titanic.apply(prop_complete)
print(cmis_col)
print(pmis_col)
print(pcom_col)

'''
survived         0
pclass           0
sex              0
age            177
sibsp            0
parch            0
fare             0
embarked         2
class            0
who              0
adult_male       0
deck           688
embark_town      2
alive            0
alone            0
dtype: int64
survived       0.000000
pclass         0.000000
sex            0.000000
age            0.198653
sibsp          0.000000
parch          0.000000
fare           0.000000
embarked       0.002245
class          0.000000
who            0.000000
adult_male     0.000000
deck           0.772166
embark_town    0.002245
alive          0.000000
alone          0.000000
dtype: float64
survived       1.000000
pclass         1.000000
sex            1.000000
age            0.801347
sibsp          1.000000
parch          1.000000
fare           1.000000
embarked       0.997755
class          1.000000
who            1.000000
adult_male     1.000000
deck           0.227834
embark_town    0.997755
alive          1.000000
alone          1.000000
'''

统计缺失值,可以用于判断某列是否适合用于分析

从结果看embark_town列只包含两个缺失值 检查行很容易

print(titanic.loc[pd.isnull(titanic.embark_town),:])
'''
     survived  pclass     sex   age  ...  deck  embark_town  alive alone
61          1       1  female  38.0  ...     B          NaN    yes  True
829         1       1  female  62.0  ...     B          NaN    yes  True
'''

2.2 按行应用

#应用于各行
cmis_row = titanic.apply(count_missing,axis=1)   #输出各行有多少个缺失值
pmis_row = titanic.apply(prop_missing,axis=1)
pcom_row = titanic.apply(prop_complete,axis=1)
print(cmis_row.head())
print(pmis_row.head())
print(pcom_row.head())
'''
0    1
1    0
2    1
3    0
4    1
dtype: int64
0    0.066667
1    0.000000
2    0.066667
3    0.000000
4    0.066667
dtype: float64
0    0.933333
1    1.000000
2    0.933333
3    1.000000
4    0.933333
dtype: float64
'''
#因为按行使用apply,可以创建一个包含这些值的新列,(在末端加入一列显示该行缺失总数
titanic['num_missing'] = titanic.apply(count_missing,axis=1)
print(titanic.head())
#通过最后一列,排查包含多个缺失值的行
print(titanic.loc[titanic.num_missing>1,:].sample(10))  #sample(10)随机抽取10行
'''
   survived  pclass     sex   age  ...  embark_town  alive  alone num_missing
0         0       3    male  22.0  ...  Southampton     no  False           1
1         1       1  female  38.0  ...    Cherbourg    yes  False           0
2         1       3  female  26.0  ...  Southampton    yes   True           1
3         1       1  female  35.0  ...  Southampton    yes  False           0
4         0       3    male  35.0  ...  Southampton     no   True           1

[5 rows x 16 columns]
     survived  pclass     sex  age  ...  embark_town  alive  alone num_missing
470         0       3    male  NaN  ...  Southampton     no   True           2
557         0       1    male  NaN  ...    Cherbourg     no   True           2
413         0       2    male  NaN  ...  Southampton     no   True           2
.......
'''

3 向量化函数

#函数内部本质是向量化的,会自动对每个元素做加法
print(avg_2(df['a'],df['b']))  

#重新编写一个函数,执行非向量化计算
import numpy as np
def avg_2_mod(x,y):
    if(x==57):
        return(np.NaN)
    else:
        return (x+y/2)
#此时运行该函数会引发错误
print(avg_2_mod(df['a'],df['b']))

#但是给它单个值,又能正常工作
print(avg_2_mod(57,23))
'''
nan
'''

3.1 使用NumPy

NumPy库的vectorize函数使值向量逐个元素执行计算。

#np.vectorize创建一个新函数,将其向量化
avg_2_mod_vec = np.vectorize(avg_2_mod)
print(avg_2_mod_vec(df['a'],df['b']))
#也可以使用python装饰器自动把函数向量化,无需创建新函数
#但是必须要在函数前使用
@np.vectorize
def avg_2_mod(x,y):
    if(x==57):
        return(np.NaN)
    else:
        return (x+y)/2
print(avg_2_mod(df['a'],df['b']))
'''
[24.   nan 37.5 44. ]
'''

3.2 使用numba

numba也有一个vectorize装饰器

import numba
@numba.vectorize
def avg_2_numba(x,y):
    if(int(x) == 57):        #现在必须向函数添加类型信息
        return(np.NaN)
    else:
        return (x+y)/2
#运行结果失败,numba不支持pandas对象
print(avg_2_numba(df['a'],df['b']))

#要把数据表示成Numpy数组并传入
print(avg_2_numba(df['a'].values,df['b'].values))
'''
[24.   nan 37.5 44. ]
'''

4 lambda函数

可以从数据行提取需要的信息(匹配),赋给新的一列

import pandas
df = pandas.read_csv('...ge/gapdata10.csv',encoding="utf-8",sep=',')
print(df)

import regex
p = regex.compile('\w+\w+')       #匹配模式
def get_abc(s):                   #先编辑一个函数
    return p.match(s).group()

df['c+'] = df['c'].apply(get_abc) #再调用Apply应用
print(df)
'''
      a     b        c    d       c+
0   bbc   cgf  bf43543  248  bf43543
1  fsdf   fgd    dv425  654    dv425
'''

可以直接将函数代码写入apply方法中,即运用lambda函数 

#lambda函数可以编写复杂的函数,但是通常只有在简单计算时使用
df['c++'] = df['c'].apply(lambda x: p.match(x).group())
print(df)
'''
      a     b        c    d       c+      c++
0   bbc   cgf  bf43543  248  bf43543  bf43543
1  fsdf   fgd    dv425  654    dv425    dv425
'''
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值