day09数据分析
query筛选
abb_pop_area.query('year == 2010 & ages == "total"')
map
apply
transform
删除重复数据
drop_per
删除空置数据
drop
add_per_
删除异常数据
twict = stu()
df.notnull().all(axis=1) #相反的, 组合使用 notnull all
df.loc[df.notnull().all(axis=1)]
过滤df中的空值(只保留没有空值的行)
df.dropna(axis=0) #
效果一样:
df.loc[df.notnull().all(axis=1)]
df.dropna(axis=0)
练习7:
简述None与NaN的区别
假设张三李四参加模拟考试,但张三因为突然想明白人生放弃了英语考试,因此记为None,请据此创建一个DataFrame,命名为ddd3
老师决定根据用数学的分数填充张三的英语成绩,如何实现? 用李四的英语成绩填充张三的英语成绩?
# import random # 不用引入
ddd = DataFrame(data =np.random.randint(90,130,size=(2,2)),index=['英语','数学'],columns=['张三','李四'])
ddd
ddd.loc['数学','张三'] = np.nan
ddd
ddd.fillna(method='ffill',axis=0)
ddd.fillna(method='bfill',axis=1)
张三 | 李四 | |
---|---|---|
英语 | 93.0 | 103.0 |
数学 | 91.0 | 91.0 |
处理丢失数据
有两种丢失数据: None np.nan(NaN)
type(None)---->NoneType
type(np.nan)------>float
np.nan+1------->nan
将某些数组元素赋值为nan
df.iloc[2,4] = None
df.iloc[5,5] = np.nan
df.iloc[2,2] = None
df.iloc[7,3] = None
df.iloc[6,8] = None # 自动转化成nan
df
# pandas 处理空值操作
df.isnull().any(axis=1)# axis =1 是行, drop axis=0 是行
df.notnull().all(axis=1) #相反的, 组合使用 notnull all
df.loc[df.notnull().all(axis=1)]
过滤df中的空值(只保留没有空值的行)
df.dropna(axis=0) #
df.fillna(method='ffill',axis=0)# 列 前 +
2 的拼接操作
1.使用pd.concat()级联
1)匹配级联
pd.concat((df1,df1),axis=1,join='inner')
pd.concat((df1,df1),axis=0,join='inner')
1)非匹配级联
pd.concat((df1,df2),axis=0,join='inner')
2.使用pd.merge()合并
merge与concat的区别在于,merge需要依据某一共同的列来进行合并
使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
注意每一列元素的顺序不要求一致
参数:
how:out取并集 inner取交集
on:当有多列相同的时候,可以使用on来指定使用那一列进行合并,on的值为一个列表
1) 一对一合并
df1 = DataFrame({
'employee':['Bob','Jake','Lisa'],
'group':['Accounting','Engineering','Engineering'],
})
df2 = DataFrame({
'employee':['Bob','Jake','Lisa'],
'hire_date':[2004,2008,2012],
})
pd.merge(df1,df2)
- 多对一合并
pd.merge(df3,df4)
3) 多对多合并
pd.merge(df5,df6,how='outer')
4) key的规范化
当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
pd.merge(df1,df2,on='employee')
5) 内合并与外合并:
out取并集 inner取交集¶
内合并:只保留两者都有的key(默认模式)
外合并 how='outer':补NaN
作业
- 案例分析:美国各州人口数据分析¶
1.删除重复元素
使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True
- keep参数:指定保留哪一重复的行数据
创建具有重复元素行的DataFrame
创建一个df
df = DataFrame(data=np.random.randint(0,100,size=(9,5)))
df.iloc[1] = [6,6,6,6,6]
df.iloc[3] = [6,6,6,6,6]
df.iloc[5] = [6,6,6,6,6]
df
- 使用drop_duplicates()函数删除重复的行
- drop_duplicates(keep='first/last'/False)
df.drop_duplicates(keep='first')
df.drop_duplicates(keep='last')
2.映射
1) replace()函数:替换元素
DataFrame替换操作
- 单值替换
- 普通替换: 替换所有符合要求的元素:to_replace=15,value='e'
- 按列指定单值替换: to_replace={列标签:替换值} value='value'
- 多值替换
- 列表替换: to_replace=[] value=[]
- 字典替换(推荐) to_replace={to_replace:value,to_replace:value}
替换一行
df.replace(to_replace=6,value='six')
替换单个值
df.replace(to_replace={4:'four'})
df.replace(to_replace={4:6},value='six') #指定 第四行为6的元素换成six
2)map()函数:
新建一列 , map函数并不是df的方法,而是series的方法¶-map()函数:新建一列-,---map函数并不是df的方法,而是series的方法)
- map()可以映射新一列数据
- map()中可以使用lambd表达式
- map()中可以使用方法,可以是自定义的方法
eg:map({to_replace:value})
- 注意 map()中不能使用sum之类的函数,for循环
- 新增一列:给df中,添加一列,该列的值为中文名对应的英文名
映射
dic = {
'jay':'周杰伦',
'tom':'张三'
}
df['c_name'] = df['name'].map(dic)
df
map当做一种运算工具,至于执行何种运算,是由map函数的参数决定的(参数:lambda,函数)
- 使用自定义函数
def after_sal(s):
return s- (s-5000)*0.5
超过5000部分的钱缴纳50%的税
df['after_sal'] = df['salary'].map(after_sal)
apply()函数
也可以运算
df['salary'].apply(after_sal)#返回的是索引
注意:并不是任何形式的函数都可以作为map的参数。只有当一个函数具有一个参数且有返回值,那么该函数才可以作为map的参数。
3.使用聚合操作对数据异常值检测和过滤
使用df.std()函数可以求得DataFrame对象每一列的标准差
- 创建一个1000行3列的df 范围(0-1),求其每一列的标准差
df = DataFrame(data=np.random.random(size=(1000,3)),columns=['A','B','C'])
df.head()
df
对df应用筛选条件,去除标准差太大的数据:假设过滤条件为 C列数据大于两倍的C列标准差
std_twice = df['C'].std() * 2
std_twice
df['C']>std_twice
异常值对应的行数据
df.loc[df['C']>std_twice]
indexs = df.loc[df['C']>std_twice].index
df.drop(labels=indexs, axis=0, inplace=True)
df
- 数据清洗
- 清洗空值
- dropna fillna isnull notnull any all
- 清洗重复值
- drop_duplicates(keep)
- 清洗异常值
- 异常值监测的结果(布尔值),作为清洗的过滤的条件
- 清洗空值
4. 排序
使用.take()函数排序
- take()函数接受一个索引列表,用数字表示,使得df根据列表中索引的顺序进行排序
- eg:df.take([1,3,4,2,5])
可以借助np.random.permutation()函数随机排序
df.take([2,1,0],axis=1)# 隐性索引的 为了方便自动生成?
df.take([2,1,0],axis=1).take(np.random.permutation(500),axis=0)#随机排序
随机取20行
df.take([2,1,0],axis=1).take(np.random.permutation(500),axis=0)[0:20]
- np.random.permutation(x)可以生成x个从0-(x-1)的随机数列
随机抽样
当DataFrame规模足够大时,直接使用np.random.permutation(x)函数,就配合take()函数实现随机抽样
5. 数据分类处理【重点】
数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。
数据分类处理:
- 分组:先把数据分为几组
- 用函数处理:为不同组的数据应用不同的函数以转换数据
- 合并:把不同组得到的结果合并起来
数据分类处理的核心:
- groupby()函数
groups属性查看分组情况- eg: df.groupby(by='item').groups
分组
- 使用groupby实现分组
df.groupby(by='item')
<pandas.core.groupby.DataFrameGroupBy object at 0x000000000E3D5BA8>
-
使用groups查看分组情况
-
该函数可以进行数据的分组, 但是不显示分组情况
df.groupby(by='item').groups
{'Apple': Int64Index([0, 5], dtype='int64'),
'Banana': Int64Index([1, 3], dtype='int64'),
'Orange': Int64Index([2, 4], dtype='int64')}
给df创建一个新列, 内容为各个水果的平均价格
df.groupby(by='item').mean()['price'] # 增加记算量,不提倡
mean_price = df.groupby(by='item')['price'].mean()
dic = mean_price.to_dict()
dic
{'Apple': 3.0, 'Banana': 2.75, 'Orange': 3.5}
df['mean_price'] = df['item'].map(dic) # 加到表中
df
计算出苹果的平均价格
按颜色查看各种颜色的水果的平均价格
汇总:将各种颜色水果的平均价格和df进行汇总
df[df['item']=='Apple']['price'].mean()
df.groupby(by='color')['price'].mean().to_dict()
df['color_price'] = df['color'].map(df.groupby(by='color')['price'].mean().to_dict())
df
6.0 高级数据聚合
使用groupby分组后,也可以使用transform和apply提供自定义函数实现更多的运算
- df.groupby('item')['price'].sum() <==> df.groupby('item')['price'].apply(sum)
- transform和apply都会进行运算,在transform或者apply中传入函数即可
- transform和apply也可以传入一个lambda表达式
def my_mean(s):
print(s) # Name: Apple, dtype: float64
sum = 0
for i in s:
sum+=i
return sum/s.size
df.groupby(by='item')['price'].transform(my_mean)# 返回的是索引 自定义平均价格
返回的是一个个的[苹果s],[香蕉s],[西瓜s]
df.groupby(by='item')['price'].apply(my_mean)