2022年 11月 5日

python数据清洗

python数据清洗整理

建模比赛中有时会遇到海量的数据,不规整的xlsx或者csv文件,或者需要用重复的操作处理批量的表格
这里整理了一些我常用的python数据清洗技巧


字典dict

字典又称为“哈希表hashmap”、“映射”,是一种极其方便的数据结构。它通过键值对(key-value)的方式进行存储,在开发部门长期的改进与完善后,字典的存储与查找的效率非常的高。有人戏称,python将世界装进了字典中。
编码时用花括号{}封装起来,键与值之间用“:”分隔;不同的键值对之间用“,”分隔。

初始化

age={'Mike':18,'Bob':16}                        ##键与值的数据类型并没有限制
key_value={10:2,11:3}
infomation={'name':'Rise','age':18,'ID':'B19011318'}
  • 1
  • 2
  • 3

不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住

访问

  1. 访问字典的值时,后面加上[访问的值对应的键]
    如果没有该键值对,则会报错
  2. 判断字典中是否有特定键:
flag='name' in infomation
Out:
flag=True
  • 1
  • 2
  • 3

“增”

  • 增加新的键值对:
infomation["color"]='red'
  • 1
  • 将其他字典加入该字典中(update函数):
d={'Name':'Rise','color':'red','age':18}
c={'id':'B19011321'}
d.update(c)
  • 1
  • 2
  • 3

“删”

删除已有的元素:

  1. del函数:
del infomation['name']     #删除该键
del infomation             #删除整个字典
infomation.clear()         #将字典清空,变为空字典 
  • 1
  • 2
  • 3

若调用del的时候,删除的键值对不存在,则会报错

  1. pop函数:
infomation.pop('Name')
  • 1

“改”

与增加新的键值对的语法一样,但是实现效果不同。“改”则是更新键值对。

“查”

  • 返回所有键:
    编码为d.keys()。但返回类型为”dict_keys”,可以在for循环中遍历,但并不能直接查看。如要查看每一个键值可以在循环中输出,或者将结果保存为列表,即list_keys=list(d.keys())

  • 返回所有值:
    编码为d.values()。但返回类型为”dict_values”。其余同上

  • 返回所有键值对(项):
    编码为d.items()。但返回类型为”dict_items”。其余同上

  • 复制操作

dict_new=dict_old.copy()
  • 1

如果仅仅是dict_new=dict_old,当我们修改dict_new的时候,会发现dict_old随着dict_new一起发生了相同的变化。
我们做建模比赛的时候,经常使用智能算法等进行优化,需要创造新解,并且希望新解发生变化的时候旧解保持不变,方便我们将两者进行比较,这时候就不能简单地对字典整体进行赋值(其实对于list、array等数据结构来说也一样不可以)。

浅拷贝:
从本质来看,对于编译器来说dict_new这种写法实际上是引用了一个像C语言“指针”一样的东西,在C语言中我们不可以将一个数组整体进行赋值,而需要一个指针来指向这个数组的初始地址。python的整体赋值其实也是用新变量指向了原变量的初始地址,而对新变量进行修改,改变的还是原空间中存储的数据。.copy()相当>于>一次浅拷贝操作,将原来的存储空间和数据复制了一份。这时对新变量改动就不会影响到原变量了。

按照值进行排序

使用sorted函数,并且要结合lambda表达式,以下为详解:

d = {'zcy':91,'hyz':98,'ly':93,'ssy':96,'pyj':100}
#key=lambda后面随意选取一个变量,这里使用'i',i:i[0]表明第一项,即以字典的“键”进行排序
#默认为升序排列,reverse参数代表是否降序排列,reverse为True代表降序,若为False则为升序排列
c_tuple=sorted(d.items(), key=lambda i:i[1],reverse=False)    #键按照升序排列
c_tuple=sorted(d.items(), key=lambda i:i[1],reverse=True)     #键按照降序排列
c_tuple=sorted(d.items(), key=lambda i:i[1],reverse=False)    #键按照升序排列
c_tuple=sorted(d.items(), key=lambda i:i[1],reverse=True)     #键按照降序排列
#调用完sorted函数之后,返回的是一个列表,列表中的元素为元组(键,值)
#如要返回原先的字典形式,则需要
c_sorted_dict=dict(c_tuple)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

pandas库

pandas库为 Python 数据分析提供了提供快速、灵活和富有表现力的数据结构,即Series和DataFrame。旨在使“关系”或“标记”数据的使用既简单又直观。
Pandas 自诞生后被应用于众多的领域,比如金融、统计学、社会科学、建筑工程等。

使用其操作及数据结构之前必须先进行导包操作

import pandas as pd
import numpy as np
  • 1
  • 2

Python在使用pandas库的时候,往往也需要用到numpy库,因此在用到numpy的时候也要进行提前导包操作。


系列Series

Series是一种类似与一维数组的对象,由下面两个部分组成:

  1. values(值):一组数据
  2. index(索引):相关的数据索引标签(索引数据可以为连续整数,也可以自定义)

Series的结构示意图:

在这里插入图片描述

创建Series

#1.使用列表进行创建
n_list=[1,2,3,4,5]
n_series=pd.Series(n_list)
#2.使用np.array进行创建
n_array=np.array([1,2,3,4,5])
n_series=pd.Series(n_array)
#3.使用字典进行创建,此种情况下“键”为index,“值”为values
d={'Name':'Rise','color':'red','age':18}
n_dict=pd.Series(d)
#4.自定义索引值
n_array=np.array([1,2,3,4,5])
n_series=pd.Series(n_array,index=list('abcde'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

调用Series

  • 单个调用:像字典一样s["a"],或者s.loc["a"]
  • 批量调用(切片调用):
    1. 连续:n1=n_series.loc[0:3]
    2. 离散:n2=n_series.loc[[1,4]]
  • 隐式索引iloc
    前几种为显式索引loc,还可以使用隐式索引iloc
    显式索引loc索引的目标是本来的索引值,隐式索引iloc的目标是0,1,2,3……

数据帧DataFrame

DataFrame是由Series构成的,一个类似于表格的数据结构,可以看做是由Series组成的字典(共用同一个索引)。
DataFrame由按一定顺序排列的多列数据组成。它可以将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引(Series只有一个索引)。

在这里插入图片描述
DataFrame数据帧的两要素称之为indexcolumns

{

index

——行索引

columns

——列索引

\left\{

index——行索引columns——列索引

\right.

{indexcolumns——行索引——列索引

创建DataFrame

一般来说,DataFrame常从外部导入,我们并不会经常自己创建DataFrame
最常用的方式是用字典来创建。

#用字典来创建的时候,“值”中列表的长度要一致,不然会报错
dic = {
    "姓名":['zcy','hyz','ly','ssy','pyj'],
    "分数":['95','96','97','98','99'],
    "学号":['1','2','3','4','5']
}
df=pd.DataFrame(dic)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

#字典的“键”为列头,字典的index为行头
df = pd.DataFrame({"张三":150,"李四":100},index=["语文","数学","英语","理综"])
#这样做可以批量定义每一列
  • 1
  • 2
  • 3

在这里插入图片描述

DataFrame索引列的规定与修改

如果不规定哪一列为索引列,默认再加一列从0开始的连续整数作为索引列。
在DataFrame之后,可以使用set_index函数对索引列进行修改:

#用字典来创建的时候,“值”中列表的长度要一致,不然会报错
dic = {
    "姓名":['zcy','hyz','ly','ssy','pyj'],
    "分数":['95','96','97','98','99'],
    "学号":['1','2','3','4','5']
}
df=pd.DataFrame(dic)
df.set_index("姓名",inplace=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

DataFrame的调用

  1. 直接引用,如:
df['姓名']
  • 1
  1. 借助loc函数和iloc函数:
    与Series类似,DataFrame的lociloc只是将Series的单个索引变成了两个索引,这样才能访问二维数据
dic = {
    "姓名":['zcy','hyz','ly','ssy','pyj'],
    "分数":[95,96,97,98,99],
    "学号":['1','2','3','4','5']
}
df=pd.DataFrame(dic)
df.set_index("姓名",inplace=True)
score1=df.loc['zcy','分数']
score2=df.iloc[0,0]
##score1和score2结果一致
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

甚至可以引入布尔型索引:

data.iloc[:,data.columns!="某列"]
  • 1

DataFrame的“增”

行和列都可以增加

  1. 增添新列(有值新列与空列):
dic = {
    "姓名":['zcy','hyz','ly','ssy','pyj'],
    "分数":[95,96,97,98,99],
    "学号":['1','2','3','4','5']
}
df=pd.DataFrame(dic)
df.set_index("姓名",inplace=True)
df["性别"]='male'            #增加有值的新列
df["帅气程度"]=''            #增加空列
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. 增添新行:
    可使用loc或者iloc函数进行行的增添
df.loc['wc']=[100,'6','male','']      
  • 1

注意添加的维度一定要匹配,若维度不一样则会报错

DataFrame的“删”

使用drop函数进行列和行的删除

dic = {
    "姓名":['zcy','hyz','ly','ssy','pyj'],
    "分数":[95,96,97,98,99],
    "学号":['1','2','3','4','5']
}
#方式1:
df.drop(columns='学号',inplace=True)
#方式2:
df.drop('学号',axis=1,inplace=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

drop函数可以使用columns进行列的定位。也可以使用axis进行定位
对于方式1来说:

{

使用关键词“index=

,

删除某一行

使用关键词“columes=

,

删除某一行

\left\{

使用关键词“index=……”,删除某一行使用关键词“columes=……”,删除某一行

\right.

{使用关键词“index=,删除某一行使用关键词“columes=,删除某一行

对于方式2来说:

{

行定位

,

a

x

i

s

=

0

列定位

,

a

x

i

s

=

1

\left\{

行定位,axis=0列定位,axis=1

\right.

{行定位,axis=0列定位,axis=1
drop函数的inplace参数若为False,则只能通过赋值来将改动过的DataFrame赋给另一个变量;
inplace参数若为True,则无需赋值,直接在原DataFrame上进行修改。

  • DataFrame的列插入
    可使用insert函数来实现:
dic = {
    "姓名":['zcy','hyz','ly','ssy','pyj'],
    "分数":[95,96,97,98,99],
    "学号":['1','2','3','4','5']
}
df=pd.DataFrame(dic)
df["性别"]='male'
df.insert(0,'帅气程度',[0,0,0,0,0])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

同时,对于列删除来说,还可以选择del函数(直接在原数据上进行修改)

  • Dataframe的尺寸
    行数:df.shape[0]
    列数:df.shape[1]

注意这里一定要是方括号’[ ]‘而不能是圆括号’( )’

  • dropna函数
    参数:
参数名 备注
axis default 0指行,1为列
how {‘any’, ‘all’} default ‘any’指带缺失值的所有行;’all’指清除全是缺失值的
thresh int,保留含有int个非空值的行
subset 对特定的列进行缺失值删除处理
inplace 这个很常见,True表示直接在原数据上更改
df.dropna(inplace=True)     #去除包含NaN 的行
  • 1

pandas库应用

取某一列所有的元素

df["该列"].unique().tolist()
  • 1
  • 除此之外还可以使用集合set

布尔索引

  • 保留某一列中等于特定值的行

    df[df["国家"]=='中国']			# 取出所有有关中国的行
    
    • 1
  • 删除某一列中等于特定值的行

    df[~(df["国家"]='中国')]		# 删除所有有关中国的行
    
    • 1
  • 取出某一列中的特定行,其在该列的值在某个列表中

    country_list=['中国','美国','法国']
    df[df["国家"].isin(country_list)]
    
    • 1
    • 2
  • 组合逻辑条件

    • 多个都满足使用&
    • 多个满足一个即可使用|
  • 布尔索引并不局限于DataFrame中,也可以使用在列表中,或者np.array

    import numpy as np
    
    a=np.array([[1,2,3],[2,3,4]])
    b=a[a>=3]
    
    • 1
    • 2
    • 3
    • 4

导入数据

  • 导入csv文件:
    使用read_csv()函数:
    read_csv()中的参数
参数 作用 备注
(url) 引入文件路径(相对路径或者绝对路径) r"……"
header 指定从第几行开始计数 指定行数用来作为列名,数据开始行数。如果文件中没有列名,则默认为0,否则设置为None。
index_col 索引列 指定索引列。这里不用整数作为索引,而是使用真实的索引列名称
  • 导入excel:
    使用read_excel()函数:
    read_excel()中的参数
参数 作用 备注
(url) 引入文件路径(相对路径或者绝对路径) r"……"
header 指定从第几行开始计数 指定行数用来作为列名,数据开始行数。如果文件中没有列名,则默认为0,否则设置为None。
index_col 索引列 指定索引列。这里不用整数作为索引,而是使用真实的索引列名称