Pandas_数据清洗与整理_全
# 数据清洗与整(全)
# 1) 常见的数据清洗方法
# 2) 数据合并:多源数据的合并和连接
# 3) 数据重塑:针对层次化索引,学会 stack和 unstack
# 4) 字符串处理:学会 DataFrame中字符串函数的使用
# 一,常见的数据清洗方法
# 1, 查看数据基本信息
# df.info()
# df.describe()
# df.head(n): 显示数据前n行,不指定n,df.head()则会显示所有的行
# 2, 侦查缺失值
# df.isnull() :返回一个和 df结构相同的布尔型 DataFrame矩阵
# df.isnull().sum() :返回一个以 df各【列】值为nan个数为元素的序列
# df.isnull().sum().sum() :返回 df所有的 值为nan的个数和。
# df.notnull() :返回一个和 df结构相同的布尔型 DataFrame矩阵
# df.notnull().sum() :返回一个以 df各【列】值为非nan个数为元素的序列
# df.isnull().sum().sum() :返回 df所有的 值为非nan的个数和。
import numpy as np
import pandas as pd
from pandas import DataFrame,Series
df=DataFrame([[3,5,np.nan],[1,3,np.nan],['tom',np.nan,'ivan'],[np.nan,'a','b']])
df
df.isnull()
df.isnull().sum()
df.isnull().sum().sum() # 4
df.notnull()
df.notnull().sum()
df.notnull().sum().sum() # 8
# 3, 删除存在缺失值的整行或整列
# 不影响原 DataFrame数据
df.dropna(how='any',axis=0) # 删除含有 NaN的整行数据 当 how='any'时,可以缺省
df.dropna(how='all',axis=0) # 删除所有值为 NaN的整行数据
df.dropna(how='any',axis=1) # 删除含有 NaN的整列数据 当 how='any'时,可以缺省
df.dropna(how='all',axis=1) # 删除所有值为 NaN的整列数据
# 4, 填充缺失值
# df.fillna? 查看函数帮助
# 当存在缺失值的行或列中的那些非缺失值很重要时,不能将整行或整列一删了之,这时需要填充缺失值:
df=DataFrame([[3,5,np.nan],[1,3,np.nan],['tom',np.nan,'ivan'],[np.nan,'a','b']])
df2=DataFrame([[0,1,2,np.nan],[4,5,6,np.nan],[np.nan,np.nan,np.nan,np.nan]])
# 对所有的 NaN 填充数据:
df3=df.fillna(0,inplace=False) # 将 DataFrame中的所有 NaN填充为 0 inplace缺省时默认 inplace=False
df.fillna(0,inplace=True) # 就地修改
# 对指定的某列或某几列填充数据 -- 1 使用索引和切片调用 fillna():
df[0].fillna(df[0].mean()) # 填充第 1列,使用第一列的统计非 NaA的平均值。
df[0:2]=df[0:2].fillna('enene') # 填充第 1-3列,使用'enene'
df
df[[0,2]]=df[[0,2]].fillna('dada') # 填充第 1,3两列,使用'dada' 注意区别 df[[0,2]] 与 df[0,2]的不同,别用混了
df
# 对指定的某列或某几列填充数据 -- 2 fillna()的参数传入字典:
df.fillna({0:df[0].mean()}) # 填充第 1列,使用第一列的统计非 NaA的平均值。
df2.fillna({0:0,2:'aa'}) # 给指定的列填充 第一列的填充值为 0,第 3列的填充值为 'aa'
df.fillna(method='ffifll') # df.reindex()里也有这个参数
# 对指定的某行或某几行填充数据 -- 1 使用索引和切片调用 fillna():
df.loc[0].fillna(df.loc[0].mean(),inplace=True) # 填充第 1行,使用第一行的统计非 NaA的平均值。
df.loc[0:2]=df.loc[0:2].fillna('enene') # 填充第 1-3行,使用'enene'
df
df.loc[[0,2]]=df.loc[[0,2]].fillna('dada') # 填充第 1,3两行,使用'dada'
df
# 对指定的某行或某几行填充数据 -- 2 fillna()的参数传入字典:(不推荐)
# 给行填充不能使用字典参数加 axis=1的方式,会报错的,但可以使用转置的方法转成列再填充,然后转置回来。
df=df.T.fillna({2:'aa'}).T
df=df.T.fillna({0:0,3:'aa'}).T # 给指定的行填充 转置两次
# 5, 移除重复数据
# 移除行数据完全相同的行:
df.duplicates() # 返回一个布尔型序列 True表示与前面行数据有重复
df.drop_duplicates() # 保留第一次出现的行数据,删除其他的重复行数据 keep='first' 可缺省
df.drop_duplicates(keep='last') # 保留最后一次出现的行数据,删除其他的重复行数据
# 移除以指定列所谓判断重复标准的的行:
df.drop_duplicates(subset=['sex','year'],keep='last') # 以指定的'sex','year'列作为判断依据。
# 6, 替换值:df.replace()
df.replace('','未知') # 将 df中所有的 ""替换为 "未知"
df.replace(['',2001],['未知',2002]) # 将 df中所有的 ""替换为 "未知",将 2001替换为 2002
df.replace({'':'未知',2001:2002}) # 将 df中所有的 ""替换为 "未知",将 2001替换为 2002
# 7, 利用函数或映射进行数据转换
# 判断分数等级:90-100 优秀; 70-89 良好; 60-69 及格; <60 不及格
# python可以使用 循环加 if 判断来解决
# pandas 可以使用 自定义函数+map()函数来实现
data={
'name':['张三','李四','王五','马六'],
'grade':[75,52,63,99]
}
df=DataFrame(data)
def f(x):
if x>=90:
return '优秀'
elif 70<=x<90:
return '良好'
elif 60<=x<70:
return '合格'
else:
return '不合格'
df['class']=df.grade.map(f) # df['class']=df['grade'].map(f)
df
# 8, 检测异常值
df=DataFrame(np.arange(10),columns=['X'])
df['Y']=df['X']*2+0.5
df.iloc[9,1]=185 # 将第 9行第 1列的值由 18.5改为 185
df.plot(kind='scatter',x='X',y='Y')
# 9, 虚拟变量(暂时用不到,数学建模机器学习)
# 对于单类别的数据:使用 pd.get_dummies()
df = DataFrame(
{
'朝向':['东','南','东','西','北']
'价格':[1200,2000,1200,1100,800]
}
)
df
pd.get_dummies(df['朝向'])
# 对于多类别的数据:使用 apply()
df = DataFrame(
{
'朝向':['东/北','南/西','东','西/北','北']
'价格':[1200,2000,1200,1100,800]
}
)
df
dummies=df['朝向'].apply(lambda x:Series(x.split('/')).value_counts())
dummies
# 二,数据合并与重塑
# 当要数据来源于多处时,就需要对数据进行合并和重塑。
# 1, pd.merge(df1,df2,on='fruit',how='inner'...)函数:
# how--how='inner' 内连接,交集(默认)
# how='outer' 外连接,并集
# how='left'左连接 以 df1为主表,右表没数据为 NaN
# how='right'右连接 以 df2为主表,右表没数据为 NaN
# left--指参数列表里第一个 Daframe
# right--指参数列表里第二个 Daframe
# on--用于连接的列名
# left_on--df1用于连接的列名 与 right_on--df2用于连接的列名 成对出现
# left_index--df1的行索引作为连接键 因为行索引也可以看作是一列
# right_index--df2的行索引作为连接键
# sort--合并后对数据进行排序,默认为True
# suffixes--修改重复名
# 通过一个键或多个键(DataFrame的列)将两个DataFrame按行合并起来,类似于SQL。
price=DataFrame(
{
'fruit':['apple','banana','orange'],
'price':[23,32,45]
}
)
amount=DataFrame(
{
'fruit':['apple','banana','apple','apple','banana','pear'],
'amount':[5,3,6,3,5,7]
}
)
pd.merge(amount,price,on='fruit') # 交集
pd.merge(amount,price,on='fruit',how='outer') # 并集
pd.merge(amount,price,on='fruit',how='left') # 左连接
# 多对多的连接,笛卡尔积:
# 只使用一个键来连接时,price2里有2个 apple,amount2里有3个apple,连接的结果就有6个apple.
price2=DataFrame(
{
'fruit':['apple','banana','orange','apple'],
'price':[23,32,45,25]
}
)
amount2=DataFrame(
{
'fruit':['apple','banana','apple','apple','banana','pear'],
'amount':[5,3,6,3,5,7]
}
)
pd.merge(amount2,price2,on='fruit',how='outer') # 并集
# 多个键合并,使用列表:
df1=DataFrame(
{
'k1':['one','one','two'],
'k2':['a','b','a'],
'v1':[2,3,4]
}
)
df2=DataFrame(
{
'k1':['one','one','two','two'],
'k2':['a','a','a','b'],
'v1':[5,6,7,8]
}
)
# pd.merge(df1,df2,on='k1',how='outer') # 当只指定一个连接键的时候,容易出现笛卡尔积
pd.merge(df1,df2,on=['k1','k2'],how='outer') # 用两个连接键作为约束,就可以避免不必要的笛卡尔积
# suffixes 处理重复列名的问题:
pd.merge(df1,df2,on='k1',how='outer',suffixes=('_left','_right')) # suffixes 处理重复列名的问题
# 使用行索引作为连接键来使用:right_index=True 或 left_index=True
df1=DataFrame(
{
'k':['a','b','a'],
'v1':[2,3,4]
}
)
df2=DataFrame({'v2':[5,6,7,8]}index=['a','b'])
pd.merge(df1,df2,left_on='key',right_index=True)
# 将两个Dataframe同时按照索引连接起来:
# 1)方法一,使用 merge:
pd.merge(df1,df2,left_on='k',left_index=True,right_index=True,how='outer')
# 2)方法二,使用 join:
df1.join(df2,how='outer')
# 2, pd.concat([s1,s2],axis=0,join='outer',join_axes=[['b','a']])
# 默认 axis=0 默认 join='outer' join只有 inner和 outer两个值可选. join_axes用来指定索引顺序
# 当要合并的两个 DataFrame没有连接键时,不能使用 merge,可以使用 contact。
# concat只会连接不会去重。想要对结果去重,得使用 df.drop_duplicates()。
# 对于 Series:
s1=Series([0,1],index=['a','b'])
s2=Series([0,3],index=['a','d']) # a标签与 s1重复
s3=Series([4,5],index=['e','f'])
pd.concat([s1,s2,s3]) # 共 6行 1列 axis=0
pd.concat([s1,s2,s3],axis=1) # 共 5行 3列 axis=1
pd.concat([s1,s2],axis=1,join='outer') # join='outer' 并集 2列 3行 a b d
pd.concat([s1,s2],axis=0,join='outer') # join='outer' 并集 1列 4行 a b a d 默认
pd.concat([s1,s2],axis=1,join='inner') # join='inner' 交集 2列 1行 a
pd.concat([s1,s2],axis=0,join='inner') # join='inner' 交集 1列 4行 a并集 默认
# 如果想在结果中很容易区分出参与连接的对象,可以使用 keys参数给连接对象创建一个层次化索引。
pd.concat([s1,s2],axis=0,join='inner',keys=['first','second'])
pd.concat({'first':s1,'second':s2},axis=0,join='inner')
pd.concat([s1,s2],axis=1,join='inner',keys=['first','second'])
pd.concat({'first':s1,'second':s2},axis=1,join='inner')
# 对于 DataFrame:
price=DataFrame(
{
'fruit':['apple','banana','orange'],
'price':[23,32,45]
}
)
amount=DataFrame(
{
'fruit':['apple','banana','apple','apple','banana','pear'],
'amount':[5,3,6,3,5,7]
}
)
pd.concat([price,amount],axis=1)
# 重新生成默认索引:对于 axis=0时有用
price=DataFrame(
{
'fruit':['apple','banana','orange'],
'price':[23,32,45]
},index=['a','b','c']
)
amount=DataFrame(
{
'fruit':['apple','banana','apple','apple','banana','pear'],
'amount':[5,3,6,3,5,7]
},index=['a','b','c','d','e','f']
)
pd.concat([price,amount],axis=0)
pd.concat([price,amount],axis=0,ignore_index=True) # 不会改变数据结构,只是生成新的默认索引
# 3, combine_first()合并
# combine_first()使用的连接键是行索引(行索引可以看作为一个列)
# 如果需要合并的两个 DataFrame存在重复的索引,在这种情况下,若使用 merge和 concat方法都不能准确的解决问题,此时需要
# combine_first方法,类似于打补丁,以调用的 DataFrame为主,参数里的 DataFrame作为补丁。
price=DataFrame(
{
'fruit':['apple','banana',np.nan,'pear'],
'price':[23,32,np.nan,np.nan]
},index=['a','b','c','d']
)
amount=DataFrame(
{
'fruit':['apple','banana','apple','apple','banana','pear'],
'price':[5,3,6,3,5,7],
'amount':[1,1,1,1,1,1]
},index=['a','b','c','d','e','f']
)
price.combine_first(amount)
# 4, 数据重塑 stack 堆叠
# 1) df.stack()方法: 将每个行索引对应的列索引堆叠起来形成内层行索引变成层次化索引的序列 Series
# 2) df.unstack()方法: df.stack()的反操作。
df=DataFrame(np.arange(9).reshape(3,3),index=['a','b','c'],columns=['one','two','three'])
df.index.name='alph'
df.columns.name='number'
Se=df.stack() # 其结果是一个层次化的序列
type(Se) # pandas.core.series.Series
Se.unstack(),Se.unstack(1),Se.unstack('number')
# unstack() 可以指定参数,默认是 Se的内层索引的名字(即原 DataFrame df1的columns.name)或表示层次结构的数字 1
# 如果将参数指定为 0或 Se的外层索引的名字(即原 DataFrame df1的index.name),则得到 df1的转置。
Se.unstack(0),Se.unstack('alph')
# 对于本身就是层次化索引的 DataFrame,其 stack()和 unstack()用到再说吧。
# 三, 字符串处理
# 1) Python 内建字符串方法:
# str.count() 返回字符串在字符串中的非重叠出现的次数
# str.endwith() 如果字符串以后缀结尾则返回 True
# str.startwith() 如果字符串以后缀结尾则返回 True
# str.join() 使用字符串作为间隔,用于黏合其他字符串的序列
# str.index() 如果在字符串中找到,则返回字符串的第一个字符的位置,如果找不到,则引发 ValueError
# str.find() 类似于 str.index(),只是找不到时返回 -1.
# str.rfind() 返回目标字符串在字符串中最后出现的位置,找不到则返回 -1.
# str.replace() 使用一个字符串替代另一个字符串
# str.strip(),str.rstrip().str.lstrip() 修剪空白,包括换行符;
# str.split() 使用分隔符将字符串拆分为子字符串的列表
# str.lower() 将大写字母转换为小写字母
# str.upper() 将小写字母转换为大写字母
# str.casefold() 将字符串转换为小写,并将任何特定于区域的变量字符串组合转换为常见的可比较的形式
# str.ljust(),str.rjust() 左对齐或右对齐;用空格(或其他一些字符)填充字符串的相反侧以返回具有最小宽度的字符串。
# 2) pandas 处理字符串数据的矢量化函数:
# https://blog.csdn.net/dta0502/article/details/81839048
# 向量化字符串方法:
# se.str.cat() 根据可选的分隔符,按元素黏合字符串
# se.str.contains() 返回是否含有某个模式/正则表达式的布尔值数组
# se.str.count() 模式出现次数的计算
# se.str.extract() 使用正则表达式从字符串 Series中分组抽取一个或多个字符串;返回的结果是每个分组形成一列的 DataFrame
# se.str.endswith() 等价于每个元素使用 x.endwith(模式)
# se.str.startswith() 等价于每个元素使用 x.startswith(模式)
# se.str.match() 使用 re.match()将正则表达式应用到每个元素上,将匹配分组以列表的形式返回。
# se.str.findall() 找出字符串中所有的模式/正则表达式匹配项,以列表返回。
# se.str.get() 对每个元素进行索引 (获取第 i 个元素)
# se.str.isalnum() 等价于内建的 str.alnum()
# se.str.isalhpa() 等价于内建的 str.isalhpa()
# se.str.isdecimal() 等价于内建的 str.isdecimal()
# se.str.isdigt() 等价于内建的 str.isdigt()
# se.str.islower() 等价于内建的 str.islower()
# se.str.isupper() 等价于内建的 str.isupper()
# se.str.isnumeric() 等价于内建的 str.isnumeric()
# se.str.join() 根据传递的分隔符,将 Series中的字符串联合
# se.str.len() 计算每个字符串的长度
# se.str.lower/se.str.upper() 对每个元素进行 大小写转换
# se.str.repeat() 重复值(如, se.str.repeat(3))
# se.str.replace() 以其他字符串替代模式/正则表达式的匹配项
# se.str.slice() 对 series中的字符串进行切片
# se.str.split() 以分隔符或正则表达式对字符串进行拆分
# se.str.strip() 对字符串的两侧的空白进行消除,包括换行符。
# se.str.rtrip() 对字符串的右侧的空白进行消除。
# se.str.ltrip() 对字符串的左侧的空白进行消除。
# se.str.pad() 将空白加到字符串的 左边,右边,或者两边
# se.str.center() 等价于 pad(side='both')
# 1, 字符串方法:以 str.split() 为例:
# 示例,将一列字符串数据分成两列:
data={
'data':['张三|男','李四|女','王五|女','马六|男']
}
df=DataFrame(data)
# 传统方法 1:
df['name']=df['data'].apply(lambda x:x.split("|")[0])
df['gender']=df['data'].apply(lambda x:x.split("|")[1])
del df['data']
# df=df[['name','gender']] # 重新排列列的顺序
df
# 传统方法 2:
df=df['data'].apply(lambda x:Series(x.split("|"))) #
df.columns=['name','gender'] # 发现结果里没有了列名,重新按位置定义列名
# df.rename(columns={'data':'name'}, inplace = True) # 重命名列
df
# pandas 方法:
# pandas中字段的 str属性可以轻松调用字符串的方法,并矢量化到整个字段数据中:
# df['data'].str.split("|") # dataframe 的 data字段的 str属性 调用了 split()方法 返回一个以列表为元素的序列
data={
'data':['张三|男','李四|女','王五|女','马六|男']
}
df=DataFrame(data)
se=df['data'].str.split("|") # type(se) # pandas.core.series.Series
df['name']=se.str[0]
df['gender']=se.str[1]
del df['data']
df
# 2,正则表达式:
# re模块中 常用的正则表达式方法:(注意不是 pandas可用的)
# 1)findall 将字符串中的所有非重叠匹配模式以列表形式返回。
# 2)finditer 与 findall 类似,只是返回的是 迭代器
# 3)match 在字符串起始位置匹配模式,也可以将模式组件匹配到分组中;如果模式匹配上了,返回match_object对象,否则返回 None
# 4) search,split,sub,subn等详见 正则表达式那个总结。
# 字符串的矢量化操作同样适用于正则表达式:
df=DataFrame({
'email':['100@qq.com','111@qq.com','222@qq.com']
})
se=df['email'].str.findall('(.*?)@')
type(se) # pandas.core.series.Series
df['qq']=df['email'].str.findall('(.*?)@').str.get(0)
df
import pandas as pd
from pandas import DataFrame
df=DataFrame({
'email':['100@qq.com','111@qq.com','222@qq.com']
})
# se=df['email'].str.findall('(.*?)@')
# type(se) # pandas.core.series.Series
# df['qq']=se.str.get(0) # get()是对每一个元素进行索引。
# df
df['qq']=df['email'].str.findall('(.*?)@').str.get(0) # 注,没有 str.search()方法。
df
{ vertical-align: top }
.dataframe thead th { text-align: right }
0 | 100@qq.com | 100 |
---|---|---|
1 | 111@qq.com | 111 |
2 | 222@qq.com | 222 |
Pandas_数据清洗与整理_全的更多相关文章
- phpcms标签整理_当前栏目调用
phpcms标签整理_当前栏目调用 转载 **//SQL语句调用: {pc:get sql="select * from phpcms_category where catid in($ca ...
- R语言扩展包dplyr——数据清洗和整理
R语言扩展包dplyr——数据清洗和整理 标签: 数据R语言数据清洗数据整理 2015-01-22 18:04 7357人阅读 评论(0) 收藏 举报 分类: R Programming(11) ...
- Flutter实战视频-移动电商-60.购物车_全选按钮的交互效果制作
60.购物车_全选按钮的交互效果制作 主要做全选和复选框的这两个功能 provide/cart.dart 业务逻辑写到provide里面 先持久化取出来字符串,把字符串编程list.循环list ca ...
- 大牛整理最全Python零基础入门学习资料
大牛整理最全Python零基础入门学习资料 发布时间:『 2017-11-12 11:56 』 帖子类别:『人工智能』 阅读次数:3504 (本文『大牛整理最全Python零基础入门学习资料 ...
- Pandas_基础_全
Pandas基础(全) 引言 Pandas是基于Numpy的库,但功能更加强大,Numpy专注于数值型数据的操作,而Pandas对数值型,字符串型等多种格式的表格数据都有很好的支持. 关于Numpy的 ...
- python基础全部知识点整理,超级全(20万字+)
目录 Python编程语言简介 https://www.cnblogs.com/hany-postq473111315/p/12256134.html Python环境搭建及中文编码 https:// ...
- 前端CSS规范整理_转载、、、
一.文件规范 1.文件均归档至约定的目录中. 具体要求通过豆瓣的CSS规范进行讲解: 所有的CSS分为两大类:通用类和业务类.通用的CSS文件,放在如下目录中: 基本样式库 /css/core 通用U ...
- java_eclipse_maven_svn_主题彩色插件_全屏插件
作为一名不算新手的猿猿,还来纠结IDE环境搭建实属不该,不过着实纠结了不少时间. target: eclipse + maven +svn + 设置默认编码+全屏 绕的路就不说了,直奔主题,由于mav ...
- PHP学习过程_Symfony_(3)_整理_十分钟学会Symfony
这篇文章主要介绍了Symfony学习十分钟入门教程,详细介绍了Symfony的安装配置,项目初始化,建立Bundle,设计实体,添加约束,增删改查等基本操作技巧,需要的朋友可以参考下 (此文章已被多人 ...
随机推荐
- ansible-handlers变更执行操作
1. ansible-handlers在变更执行操作 1) 编写playbook的handlers的配置文件 1 [root@test-1 bin]# vim /ansible/nginx/bin/ ...
- git冲突的表现
<<<<<<< HEAD b789 ======= b45678910 >>>>>>> 6853e5ff961e68 ...
- nrf528xx bootloader 模块介绍
1. bootloader 的基本功能: 启动应用 几个应用之间切换 初始化外设 nordic nrf52xxx的bootloader主要功能用来做DFU, 可以通过HCI, UART 或BLE通信的 ...
- CSS的背景
CSS的背景 1. 背景颜色background-color div { background-color: 颜色值; } 一般情况下元素背景颜色默认是transparent(透明). 2. 背景图片 ...
- 多测师讲解自动化测试 _RF数据库操作(上)_高级讲师肖sir
一.安装库 1.查看数据库是否按安装 1.1 DatabaseLibrary pip3 install mysqlclient-2.0.1-cp37-cp37m-win_amd64.whl dos ...
- Js电子时钟
简单版电子时钟,需要以下几个步骤 1. 封装一个函数 返回当前的时分秒 2. 使用定时器使当前以获取到的系统时间走动,每间隔一面调用 3. 把获取到的时间放到span盒子里,添加样式 效果展示 实现 ...
- pytest文档33-Hooks函数获取用例执行结果(pytest_runtest_makereport)
前言 pytest提供的很多钩子(Hooks)方法方便我们对测试用例框架进行二次开发,可以根据自己的需求进行改造. 先学习下pytest_runtest_makereport这个钩子方法,可以更清晰的 ...
- 【C语言】这种求结构体成员大小的方法,你可能需要了解一下~
在C语言编程中,有时候需要知道某结构体中某成员的大小,比如使用堆内存来存储结构体中的某成员时,需要知道该成员的大小,才好确定所需申请的空间大小.求某结构体中某成员的大小,你会怎么做? 例子: type ...
- CDH+Kylin三部曲之三:Kylin官方demo
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 上午小测1 B.序列 哈希表+数学
题目描述 \(EZ\) 每周一都要举行升旗仪式,国旗班会站成一整列整齐地向前行进. 郭神摄像师想要选取其中一段照下来.他想让这一段中每个人的身高成等比数列,展示出最萌身高差.但他发现这个太难办到了.于 ...