1. 创建多层行索引
1) 隐式构造
最常见的方法是给DataFrame构造函数的index参数传递两个或更多的数组
- Series也可以创建多层索引
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
# 期中,语文 期中,数学 期末,语文 期末,数学
data = np.random.randint(0,100,size=4)
s1 = Series(data,index=['期中','期中','期末','期末'])
s1 = Series(data,index=[['期中','期中','期末','期末'],['语文','数学','语文','数学']])
s1
s1.loc['期中','语文']
2) 显示构造
- 使用数组
# 期中 期末 语 数 外
indexes = pd.MultiIndex.from_arrays([['期中','期中','期中','期末','期末','期末'],['语','数','外','语','数','外']])
columns = ['tom','jack','rose']
# 6行 3列
data = np.random.randint(0,150,size=(6,3))
DataFrame(data=data,index=indexes,columns=columns)
使用tuple
indexes = pd.MultiIndex.from_tuples([('期中','语'),('期中','数'),('期中','外'),('期末','语'),('期末','数'),('期末','外')])
columns = ['tom','jack','rose']
data = np.random.randint(0,150,size=(6,3))
DataFrame(data=data,index=indexes,columns=columns)
使用product
最简单,推荐使用
indexes = pd.MultiIndex.from_product([['期中','期末'],['语','数','外']])
columns = ['tom','jack','rose']
data = np.random.randint(0,150,size=(6,3))
DataFrame(data=data,index=indexes,columns=columns)
2. 多层列索引
除了行索引index,列索引columns也能用同样的方法创建多层索引
features = pd.MultiIndex.from_product([['期中','期末'],['语','数','外']])
samples = ['张三','李四']
data = np.random.randint(0,150,size=(2,6))
DataFrame(data=data,index=samples,columns=features)
3. 多层索引对象的索引与切片操作¶
1)Series的操作
(1) 索引
deno: s1 = Series([100,90,80,70,60,50],index=pd.MultiIndex.from_product([['期中','期末'],['语','数','外']]))
s1 = Series([100,90,80,70,60,50],index=pd.MultiIndex.from_product([['期中','期末'],['语','数','外']]))
s1
# 所有期中成绩
s1.loc['期中']
s1.loc['期中','语']
s1.loc['期中']
type(s1.loc['期中'])
s1.loc['期中'].loc['语']
(2) 切片
s1.loc['期中':'期末']
# s1.loc['语':'数']
s1.iloc[0:4] # 虽然有多层 但是编号还和以前一样
2)DataFrame的操作
indexes = pd.MultiIndex.from_product([['期中','期末'],['语','数','外']])
columns = pd.MultiIndex.from_product([['一班','二班'],['01','02','03']])
data = np.random.randint(0,150,size=(6,6))
df1 = DataFrame(data,index=indexes,columns=columns)
df1
(1) 索引: 可以直接使用列名称来进行 列索引 以及 使用loc()对行索引
# 通过列名 对列进行 索引
# df1['一班']
df1['一班']
type(df1['一班']) # 获取到的是DataFrame
df1['一班']['01']
# 通过loc和iloc 对行进行索引
df1.iloc[0]
df1.loc['期中'].loc['语']
df1.loc['期中','语']
(2) 切片
df1.iloc[0:4]
df1.loc['期中'].loc['语':'数']
# df1.loc['期中',['语','数']]
df1.loc['期中'].loc[['语','数']]
df1['一班']
df1['一班']['02']
df1.iloc[:,0:4]
df1.loc[:,'一班'].loc[:,'01':'02']
data=np.random.randint(0,150,size=(2,8))
index=["rose","jack"]
columns=pd.MultiIndex.from_product([["期中","期末"],["一模","二模"],["语文","英语"]])
df = DataFrame(data,index,columns)
df
1. 索引的堆(stack)¶
stack()
unstack()
stack() columns -> index 列标题变行标题(程序会自动计算数据,让数据跟着标题走)
df.stack().stack().stack() # 最后把所有的索引都变到一个方向后 就成了一个Series
对于多级列索引,通过level指明要转换的columns
level 的值默认为-1(最内层);取值从外往里 从0递增
# level=-1 level 用来指明 把那一层的列索引放下去 0 1 2 3 从最外面往里走 -1 是 最里层
df.stack()
df.stack(level=-1) # 默认值是-1 是把最里层的列索引 放下去
df.stack(level=0)
unstack() index -> columns 行标题变列标题(数据也会跟着标题走)¶
df.stack().unstack(level=0)
2. 聚合操作
【注意】
- ndarray是对整个数据的操作,df默认是对列操作
- 通过指定axis,可以对行操作
data = np.random.randint(0,5,size=(5,5))
columns = list('ABCDE')
df = DataFrame(data=data,columns=columns)
df
df.sum() # dataframe默认是对列进行操作
# axis=None axis指定加和的方向 默认是列
df.sum(axis=1) # 对行进行操作
df.mean()
df.min()
df.max()
pandas数据处理
1、删除重复元素
data = [[100,100,100],[90,90,88],[100,100,100],[90,90,87],[100,100,100]]
columns = ['python','c','java']
index = list('ABCDE')
df = DataFrame(data=data,index=index,columns=columns)
df
使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True(是重复的)
使用drop_duplicates()函数删除重复的行
使用duplicate()函数查看重复的行
# duplicated() 方法 可以查找重复的样本(每一列都一样的样本)
df.duplicated() # 默认 keep='first'
df.duplicated(keep='first') # 所有重复的样本中 第一个不算重复 后面的算重复
# {'first', 'last', False}
df.duplicated(keep='last') # 所有重复的样本中 最后一个不算重复 前面的算重复
df.duplicated(keep=False) # 所有的重复都算
# drop_duplicates() 方法 可以删除重复的样本(每一列都一样的样本)
df.drop_duplicates() # 默认 keep='first'
df.drop_duplicates(keep='first')# keep='first' 所有重复样本中 保留第一个 其他的都干掉
df.drop_duplicates(keep='last')# keep='last' 所有重复样本中 保留最后一个 其他的都干掉
df.drop_duplicates(keep=False)# keep=False 不保留 所有重复的都干掉
2. 映射
映射的含义:创建一个对应关系列表,把values元素和一个特定的标签或者字符串绑定
包含三种操作:
- replace()函数:替换元素
- map()函数:新建一列
- rename()函数:替换索引
1) replace()函数:替换元素
使用replace()函数,对values进行替换操作
Series替换操作
- 单值替换
- 普通替换
- 字典替换(推荐)
- 多值替换
- 列表替换
- 字典替换(推荐)
s1 = Series(data = [100,'peppa',np.nan,'beijing'])
s1
# 单值替换
# 普通替换
s1.replace(to_replace='beijing',value='西安')
# 字典替换(推荐)
s1.replace(to_replace={'beijing':'西安'})
# 多值替换
# 列表替换
s1.replace(to_replace=[100,np.nan],value=['满分','缺考'])
# 字典替换(推荐)
s1.replace(to_replace={100:'满分',np.nan:'缺考','beijing':'西安','没有的':'也不会报错'})
# 可以放入很多没有的值 没有的值就不会替换了 但是也不会报错
# 应用:可以用来做过滤器
replace()参数:
method:对指定的值使用相邻的值填充
limit:设定填充次数
s2 = Series(data=np.array([80,100,100,100,89,78]))
s2
# methoed 参数 用来指定 从哪里找值来替换 {'pad', 'ffill', 'bfill', `None`}
s2.replace(to_replace=100) # method='pad' 默认 从前面找
s2.replace(to_replace=100,method='bfill') # 从后面找值填充
# limit 用来 设定 最大的 填充 个数
s2.replace(to_replace=100,limit=1,method='bfill')
DataFrame替换操作
-
单值替换
- 普通替换
- 按列指定的单值替换({列标签:要替换的},值)
-
多值替换
- 列表替换
- 单字典替换(推荐)
df = pd.read_excel("./data/data.xls",sheet_name=0)
df
# 单值替换
# to_replace=None, value=None
df.replace(to_replace='Beijing',value='西安')
# 按列指定的单值替换({列标签:要替换的},值)
df.replace(to_replace={4:'Beijing'},value='西安') # 指定了列 就只替换这一列中的内容 其他列不影响
# 多值替换
# 列表替换
df.replace(to_replace=['甲','乙',np.nan],value=[1,2,'空值'])
# 单字典替换(推荐)
df.replace(to_replace={'甲':1,'乙':2,np.nan:'空值','Beijing':'西安','不存在的也可以放这里':'不会报错'})
# 过滤器
2) map()函数:映射元素
- map(字典) 字典的键要足以匹配所有的数据,否则出现NaN
- map(lambda)中可以使用lambd表达式
- map(func)中可以使用方法,可以是自定义的方法
score = pd.read_excel('./data/data.xls',sheet_name=1)
score
# 映射字典
map_dic = {'小明':'北京','小红':'上海','小芳':'北京',
'小李':'广州','李元芳':'西安','狄仁杰':'西安'}
# 注意 map 是Series的方法 不是DataFrame
score['姓名'] # 每一列取出来是一个Series
score['姓名'].map(map_dic)
score['城市'] = score['姓名'].map(map_dic)
score
score['python'] = score['python'].map(lambda x:x+10)
def process_score(x):
return x-10
score['php'] = score['php'].map(process_score)
3) rename()函数:替换索引名
使用rename()函数替换行索引
- index 替换行索引
- columns 替换列索引
- level 指定多维索引的维度
df = pd.read_excel('./data/data.xls',sheet_name=2)
df
score = pd.concat((df,df))
score = pd.concat((df,df),axis=1)
score = pd.concat((df,df),axis=1,keys=['期中','期末']) # keys 可以给 两组索引 再加一层索引 用于区分
score
# mapper 是 用来映射的字典
score.rename(map_dic) # rename 默认只处理 行索引
# score.rename(map_dic)
# score.rename(index=map_dic,columns=map_dic) # 行列名都映射
score.rename(columns=map_dic) # 这样就是对列名 进行映射
# level=None用来指定映射那一层索引 默认值None 都映射
score.rename(columns=map_dic,level=0)
score.rename(columns=map_dic,level=1)
score.rename(columns=map_dic,level=-1)
3. 使用聚合操作对数据异常值检测和过滤
使用 df.describe() 函数查看每一列的描述性统计量
data = np.random.randn(1000,5) #1000行 5列 数值是符合标准正态分布的随机数
df = DataFrame(data)
df
df.describe() # 对表格数据进行描述性概览
df.std() # 对每一列 求 标准差 获取到的是 Series
根据每一列或行的标准差,对DataFrame元素进行过滤。
借助any()或all()函数, 测试是否有True,有一个或以上返回True,反之返回False
对每一列应用筛选条件,去除标准差太大的数据
df - df.mean() # DataFrame和Series相减 df的每一行和Series做减法 对应项相减
# 获取的是每个数据和平均值的差距
np.abs(df-df.mean()) # 差异的大小 如果差异很大就可以认为是异常值
np.abs(df-df.mean()) > 3*df.std() # 和平均值的差值比标准差的3倍还大
(np.abs(df-df.mean()) > 3*df.std()).any() # 这个是看那一列中有异常数据 按时我们更关系那一行有异常数据
(np.abs(df-df.mean()) > 3*df.std()).any(axis=1) # 获取了一系列的布尔值
df[(np.abs(df-df.mean()) > 3*df.std()).any(axis=1)]
删除特定索引df.drop(labels,inplace = True)
df.index # index熟悉 可以获取df的索引
df[(np.abs(df-df.mean()) > 3*df.std()).any(axis=1)] # 这也是一个df
idx = df[(np.abs(df-df.mean()) > 3*df.std()).any(axis=1)].index
idx
df1 = df.drop(labels=idx)
df1.shape
4. 排序
使用.take()函数排序
- take()函数接受一个索引列表,用数字表示
- eg:df.take([1,3,4,2,5])
可以借助np.random.permutation()函数随机排序
data = np.random.randint(0,100,size=(5,5))
index = list('ABCDE')
columns = list('甲乙丙丁戊')
df = DataFrame(data=data,index=index,columns=columns)
df
df.take([0,0,0])
df.take([0,2,4])
df.take(np.random.permutation(5)) # 只是顺序打乱 不会重复取 也不会少取
np.random.permutation(5) # 从0取到4 一共取5个 每一个取一次 只不过顺序打乱了
np.random.permutation(10)
随机抽样
当DataFrame规模足够大时,直接使用np.random.randint()函数,就配合take()函数实现随机抽样
np.random.randint(0,5,size=5)
df.take(np.random.randint(0,5,size=5))
5. 数据分类处理【重点】
数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。
数据分类处理:
- 分组:先把数据分为几组
- 用函数处理:为不同组的数据应用不同的函数以转换数据
- 合并:把不同组得到的结果合并起来
数据分类处理的核心:
- groupby()函数
- groups属性查看分组情况
df = DataFrame({'item':['苹果','香蕉','橘子','香蕉','橘子','苹果','苹果'],
'price':[4,3,3,2.5,4,2,2.8],
'color':['red','yellow','yellow','green','green','green','yello'],
'weight':[12,20,50,30,20,44,37]})
df
根据item分组,通过groups属性查看结果
df.groupby('item').groups
weight = df.groupby('item')['weight'].sum() # 获取到的是Series
weight_df = DataFrame(weight)
weight_df
把总和跟df进行merge合并
pd.merge(df,weight_df,how='left',on='item',suffixes=['','_sum'])
将'Date'设置为行索引
df.set_index('Date',inplace=True)
Series([1,2,3,4,5]).plot()
Series([1,2,3,4,3]).plot()