2.7数据的处理
2.7.1空数据的处理
2.7.1.1空数据类型
- None:是python自带的一种空数据,object,运算起来特别慢,不能进行任何的运算。
- NaN:Numpy自带的空数据类型,浮点型,可参与运算,运算之后的结果总是NaN,在pandas中NAN和None都被认为是空数据。
2.7.1.2空数据的判断
a=np.array([1,2,np.nan])
np.isnan(a) # numpy中空值的判断方法
s=pd.Series([1,2,None])
s.isnull() # pandas中空值的判断方法
df=pd.DataFrame([[1,2,np.nan],[[1,np.nan,2]]])
df.isnull()
2.7.1.3查看空数据
s=pd.Series([1,2,None,np.nan])
s[s.isnull()].index # 取出空的下标
2.7.1.4删除空数据
cond=df.isnull().any(axis=1) # 通过isnull()判断是否为空,是空返回True,否则False,使用any()通过axis=1指定只要一行当中有一个值为null那就认为是True
null_index=df[cond].index # 获取为空的索引
df1=df.drop(null_index) # 使用drop从df中删除空的数据样本
df1.info() # 查看数据中是否还存在空数据
2.7.1.5空数据填充
空数据不一定都删除,当数据量不大的时候,尽量补全,正太分布时用平均数补齐.通过我们使用fillna()函数对其进行补全,参数为:
- value需要填充的值
- method:填充的方法
- axis:轴,按行填充还是按列填充
- inplace:是否直接在原来的数据中替换
- limit:每行或者每列最多替换limit个空值
df.fillna(value='不存在')
df.fillna(value=df.mean(axis=0)) # 填充每一列的平均值
df.fillna(value=df.median(axis=0)) # 中位数
df.fillna(value=df.max(axis=0))
df.fillna(value=df.min(axis=0))
df.fillna(method='ffill') # 填充前值
df.fillna(method='bfill') # 填充后值
2.7.1.6空值运算
a=np.array([1,2,np.nan])
np.nansum(a) # 3 # 空值不计数
np.nanmean(a) #1.5 # 空值不计数
a.mean() # nan 空值计数
2.7.2重复数据处理
2.7.2.1Series祛除重复数据
s=pd.Series([1,2,3,4,3,4])
s.unique()
2.7.2.2DataFrame祛除重复数据
方法一:函数drop_duplicates()
df1.drop_duplicates(inplace=False)
方法二:drop()和duplicated()分开使用
cond=df1.duplicated() # 判断是否重复
_index=df1[cond].index # 获取重复值的所有
df1.drop(_index) # 根据索引进行删除
2.7.3数据映射函数
map、replace、apply、transform和rename的使用以及联系和区别
2.7.3.1map()函数
应用到所有元素中,不满足替换条件就赋值为None,适用于连续型,替换规则一般为函数。
df1 = pd.DataFrame(
data=np.random.randint(-50,101,size = (20,3)),
columns=['Python','En','Math']
)
def convert(x):
if x>85:
return '优秀'
elif x>70:
return '良好'
elif x>60:
return '及格'
elif x>0:
return '不及格'
level=df1.mean(axis=1).map(convert) # 数据映射
df1['等级']=level # 将Series数据存放到DataFrame数据中
df1['等级'].value_counts() # 分组统计
df1
2.7.3.2replace()函数
作用于每个元素,适用于离散型数据,替换内容一般为字典类型,不满足替换条件就不进行替换
df2= pd.DataFrame(
data=np.random.randint(-50,101,size = (20,3)),
columns=['Python','En','Math']
)
df2['sex']=pd.Series(np.random.randint(0,3,size=20))
df2['sex']=df2['sex'].replace({0:'female',1:'male'})
2.7.3.3rename()函数
- df1.rename({'等级':'level'},axis=1)
- df1.set_index()
2.8数据的拼接融合
2.8.1Numpy中数据的级联
使用axis=0指定为上下合并,axis=1指定为左右合并.
nd1=np.array([[1,2,3],[4,5,6]])
np.concatenate([nd1,nd1,nd1],axis=0)
2.8.2Pandas数据级联
2.8.2.1concat()函数
该函数通过axis=0指定为上下级联,axis=1表示左右级联,参数ingore_index可以忽原索引,join指定是内连接inner默认是外连接outer.
上下连接:
df1=pd.DataFrame(
data=np.random.randint(0,150,size=(8,4)),
columns=['Python','Java','C','C++']
)
df2=pd.DataFrame(
data=np.random.randint(0,150,size=(3,4)),
columns=['Python','Java','C','C++']
)
df2['平均值']=df2.mean(axis=1)
pd.concat([df1,df2],axis=0,ignore_index=True)
左右连接:
df1=pd.DataFrame(
data=np.random.randint(0,150,size=(3,4)),
columns=['Python','Java','C','C++']
)
df2=pd.DataFrame(
data=np.random.randint(0,150,size=(4,4)),
columns=['语文','数学','英语','理综']
)
pd.concat([df1,df2],axis=1,join='inner')
2.8.2.2merge()函数
该函数专门用来左右连接,下面是该函数的参数介绍:
- df1, # 表一
- df2, # 表二
- how='inner' # inner保留左表和右表共同的数据,outer:都保留,left保留左边,right保留右边
- left_on='_id',# 左表和右表没有共同的字段的时候,我们通过指定字段进行融合,左表字段
- right_on='id', # 右表字段
- on='age', # 如果两个表有很多共同的字段的时候,我们可以指定某个具体的字段进行合并
- suffixes=('_pre1','_pre2'), # 指定共同字段合并之后就会出现两个age,为了区分,我们在其后面添加后缀
- sort=True, # 对数据进行排序
- left_index=True, # 一般左右一起连用,如果开启,就表示根据左右索引进行关联
- right_index=True,
df1 = DataFrame({'name':['张三','张三','李四'],'salary':[12000,15000,18000]})
df2 = DataFrame({'name':['张三','张三','李四'],'address':['河北','河南','山西']})
pd.merge(df1,df2)
2.8.2.3join函数
该函数是merge的一个简化版本.
- on='name' # 指定需要关联的属性
- how='inner' # 'left', 'right', 'outer', 'inner' 四个连接方式
- lsuffix='1', # 左边的后缀
- rsuffix='2', # 右表后缀
- sort=True, # 排序
2.9数据聚合操作
2.9.1指定属性排序
方式一:自定义方法排序
df1 = pd.DataFrame(
data=np.random.randint(0,150,size=(8,4)),
index=list('ABCDEFGH'),
columns=['python','java','php','mysql'],
)
df1['总分']=df1.mean(axis=1)
sort_index=df3['总分'].argsort() # 获取排序的下标
df3.iloc[sort_index] # 取出排序之后的数据
方法二:使用Pandas中提供的方法排序
df1.sort_index() # 通过索引排序
df1.sort_values(by='总分',axis=0) # 指定具体列排序
df1.sort_values(by='H',axis=1) # 指定行排序
方法三:指定索引排序
df.take(index)
df.iloc[index]
2.9.2异常值检测
- describe():描述性统计量,随机种子random.seed(0)
- std():求每个对象的标准差
- any():借助any函数对每一列应用筛选条件.axis=0对列进行判断.eg:df2.isnull().any(axis=1) # 判断每一行有没有空数据,有的话返回True
- query('过滤条件'):举个例子:df1.query('总分>60' and 'Python>80')或者df1.query('python>java')
- info() 查看数据总体情况
2.9.3分组
2.9.3.1简单分组聚合
制造数据
df1=pd.DataFrame(
data=np.random.randint(0,150,size=(10,4)),
columns=['Python','Java','C++','C']
)
df1['sex']=np.random.randint(0,2,size=10)
df1['sex']=df1['sex'].replace({0:'男',1:'女'})
以性别分组
groups=df1.groupby(by='sex')
for group in groups:
print(group)
求出各组中指定科目的最小值
groups[['Python','Java','C++','C']].mean()
- min()
- max()
- mean()
- median()
- std()
- count()
求出各组中指定科目最小值和指定科目的最大值
groups.agg({'Python':'max','Java':'min'})
在这里也可以使用其他聚合函数,max,min,mean,std
对数据多次分组并对每个属性进行不同的处理
groups=df1.groupby(by=['sex','grade'])
groups.agg({'Python':'mean','Java':'std'})
2.9.3.2高级分组
我们可以认为是自定义聚合函数,和聚合函数的功能一样的,只不过是自定义的。因为有的时候,需要获取全部的被聚合之后的数据,用到高级聚合也就是自定义聚合的时候,通常会用到transform和apply两个重要的函数,但个人推荐使用apply函数.下面举个例子:
def convert(item):
cond=item>80
item=item[cond]
c=item.count()[0]
return {'mean':np.round(item.mean()[0],1),'count':c}
# 分组之后,一个组就是一个Series,每次调用apply都映射一个组
df1.groupby(by='grade')[['Python']].apply(convert)
transform和apply的异同点:
transform函数
- 只允许在同一时间在一个Series上进行一次转换,如果定义列‘a’ 减去列‘b’, 则会出现异常;
- 必须返回与 group相同的单个维度的序列(行)
- 返回单个标量对象也可以使用,如 . transform(sum)
apply函数:
- 不同于transform只允许在Series上进行一次转换, apply对整个DataFrame 作用
- apply隐式地将group 上所有的列作为自定义函数
2.10层次化索引
2.10.1多层索引的创建
显式索引的创建
s=pd.Series(
data=np.random.randint(0,150,size=4),
index=pd.MultiIndex.from_product([['关羽','张飞'],['期中','期末']])
)
隐式索引的创建
s=pd.Series(
data=np.random.randint(0,150,size=4),
index=pd.MultiIndex.from_tuples(
[('关羽','期中'),
('关羽','期末'),
('张飞','期中'),
('关羽','期末')]
)
)
DataFrame层次化索引
df=pd.DataFrame(
data=np.random.randint(0,150,size=(4,4)),
index=['python','java','php','mysql'],
columns=pd.MultiIndex.from_product([['周杰伦','张杰'],['期中','期末']])
)
2.10.2多层索引的索引和切片
2.10.2.1Series多层索引和切片
对于Series来说,直接中括号和.loc[]完全一样,推荐使用括号索引和切片,series进行索引的时候只需要在中括号中使用逗号分割开就可以了.
s=pd.Series(
data=np.random.randint(0,150,size=10),
index=pd.MultiIndex.from_product([list('ABCDE'),['期中','期末']])
)
s[:,'期中'] # 获取所有人期中成绩
s[['A','D']] # 获取A和D的成绩
s['A':'D'][:,'期中'] # 获取A到D的成绩
在Series中,如果我们想要进行切片,我们可以把第一层索引看成行,第二层索引看成列进行切片,如果我们想要进行索引,我们需要用两层中括号括起来,内层括号表示取出每个元素,外层括号表示这些元素对应的列表。
2.10.2.2DataFrame多层索引和切片
df=pd.DataFrame(
data=np.random.randint(0,150,size=(10,4)),
index=pd.MultiIndex.from_product([list('ABCDE'),['期中','期末']]),
columns=['Python','Java','C++','C']
)
df.loc[['B','D']][['Python','Java']] # 索引
df.loc['B':'D','Python':'C++'] # 切片
2.10.3多层索引行列转换
由外向内分别是0层、1层。
df.unstack(level=0) # 转换外层索引
df.unstack(level=1) # 转换内层索引
行列索引的转换我们使用stack函数
df.stack(level=0)
2.10.4多层索引计算
在进行多层索引计算的时候,我们不需要指定axis轴,系统会自动为我们查找哪个轴时多层索引,之不过多了level,我们用来指定它的索引层数。
df.mean(level=0) # 第一层
df.mean(level=1) # 第二层