某段代码多次被使用,且少量修改—使用函数
'''简单创建函数'''
#求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
'''