使用python数据清洗代码实例

数据读入与写出

csv

针对csv格式的数据,最简单的一种方法是用pandas中的read_csv方法,具体代码如下。其中第一个参数为待读入数据的路径,一个实用小技巧为./表示当前文件夹,../表示上层文件夹。这样如果待读入文件与代码文件在同一个文件夹下,可以节省掉很多层文件路径的输入。另外两个我较常用的参数为encoding和sep,其中encoding可指定数据UTF编码,sep为指定数据分隔符,默认为,,但我经常遇到以 为分隔符的数据。如果你遇到了类似这样的报错ParserError: Error tokenizing data. C error: Expected 1 fields in line 57, saw 3,可以考虑下是不是分隔符不对。

 Python

import pandas as pd
pd.read_csv('*.csv',encoding='gbk',sep='	')

此外,有时候一个文件太大。其分别存储在不同文件中,甚至分开存储在不同文件夹下,这时就需考虑批量读取了。 在展示代码前,先介绍一下数据背景。现在我有一个叫obj的文件夹,其中存储了一系列以’job_id='开头的文件夹,在每个文件夹中又存储了一系列以’job_id='开头的csv的文件。这些文件存储的都是同一种数据,目前我的任务是读入这一批数据,并合并成一个数据框。

 Python

file_dir=glob.glob('./obj/job_id=*')
df = pd.DataFrame()
for i in file_dir:
file=glob.glob(os.path.join(i, "job_id=*.csv"))
file.sort()
a = pd.read_csv(file[0])
for f in file[1:]:
b = pd.read_csv(f,header=None)
b.columns = a.columns
a = pd.concat([a,b],ignore_index=True)
df = pd.concat([df,tmc],ignore_index=True)

glob.glob:返回匹配的文件列表。
os.path.join:拼接文件路径。
file.sort():对文件按文件名进行排序,主要我读取的文件,按文件名排序第一的文件数据有列名,其他文件没有列名,这里就需介绍一下pd.read_csv的参数header,若header=None,则表明文件第一行非列名,否则将以列名读入python。
除了读入数据,另一个需要考虑的就是读出数据了。第一个参数指定读出的文件路径以及文件名。python中如果该文件已经存在,则直接覆盖。若不需要读出数据框的index,则选择index=False,encoding指定读出文件的UTF编码。

 Pytho

 

txt

介绍一个txt文件的读取方式。file_name为文件路径,使用with open as则在数据读入结束后能自动关闭文件夹节约内存,推荐使用这种方式。readlines自动按行读取所有文件,以列表返回,此外还可以选择realine:一次读取一行文件,read:以一个字符串读取所有文件。

 Python

with open(file_name) as file:
for line in file.readlines():
pass

这里返回的每一行数据(line),是以字符串的形式返回的,可考虑将字符串进行处理,提取需要的信息。这里介绍几个好用的字符串函数:当使用readlines时,每行数据末尾以 结束,line.rstrip():删除 string 字符串末尾的指定字符,若没有指定。默认删除空格,tab,跨行符。 line.split():按指定字符分割字符串,并以列表的形式返回。

 

数据清洗

时间处理

  • 时间的加减

 Python

import datetime
start_time = '2022-01-12 12:11:00'
time = datetime.datetime.strptime(start_time,'%Y-%m-%d %H:%M:%S')
time = time+datetime.timedelta(minutes=5)
time.strftime('%Y-%m-%d %H:%M:%S')

strptime:将字符串转化为时间格式。
+datetime.timedelta(minutes=5):在原时间基础上加5分钟,除minutes以外,还可选择的有weeks、days、hours、seconds等。同理若将+改为-,则是减掉5分钟。
strftime:将时间格式转换为字符串。

  • 显示给定时间为周几

如果是数据框,可使用如下代码:

 Python

df = pd.DataFrame({'day':['2021-11-12','2021-11-13','2021-11-14']})
pd.to_datetime(df.day).dt.weekday+1

可看出如上日期分别对应周五、周六、周天

  • 给定日期,显示为一年中的第几周。

 Python

pd.to_datetime('2021-11-12').isocalendar()[1]

isocalendar()返回时间所处的年份,以及该年的第几周,为周几,其结果对应的第二个位置,即为第几周。

  • 生成时间上的等差数列

 Python

pd.date_range(start='2021-11-12',end='2021-11-14',freq="1h",inclusive='left')

freq:控制等差数列的间隔,1h表示每一小时生成一个数。常用的选项还有D,W,M,H,min,S分别对应天、周、月、小时、分钟、秒。

inclusive:控制是否包含start和end,若为left则生成的时间等差数列不包含end对应时间,可供选择的还有both、neither、right。

 

数据聚合

  • groupby

groupby是pandas中非常好用的一个函数,其主要功能是将数据框按某一特征分组。结合相关聚合函数,能非常迅速地计算出需要的指标。 例如计算某班上男生和女生的平均身高:

 Python

df = pd.DataFrame({'性别':['男','女','女','男','男','男','女','男','男','女','女',],
 '身高':[179,160,167,170,169,180,155,177,182,158,162]})
df.groupby('性别').身高.mean().reset_index()

groupby可根据多个特征分组,需用列表表示:df.groupby(['性别','年纪'])

  • groupby+agg

利用groupby+agg将能实现非常强大的功能,且代码也更加简洁。

例如计算班上男生女生的平均身高与最高身高、最低身高

 Python

df.groupby('性别').agg({'身高':['mean','max','min']}).reset_index()
  • apply

apply函数可对数据框的行或列应用指定的方法,并返回值,默认为行。

  • 常用聚合函数

value_counts:对某一离散变量不同类别计数,默认对缺失值不计数。
count:统计非缺失值个数。
mean:求均值
median:求中位数
max:求最大值
min:求最小值
quantile:求分位数

 

批量操作

  • 列表解析式

如若需要对列表的每一个元素进行操作,并返回同样大小的列表,可考虑使用列表解析器,例如对某元素进行向上取整:

 Python

import math
lst = [1.1,1.5,2.3,4.7,2.1]
[math.ceil(i) for i in lst]
  • map

map语法为:map(function, iterable, ...),function将iterable中每一个元素作为参数调用,并返回map对象,使用list可将其转换为列表。同样对某元素进行向上取整:

 Python

list(map(math.ceil,lst))

另外还有一个map是pandas包中的map函数,功能上与上述map方法类似。此外其还有一个很好用的替换功能。例如将上面身高数据中,男生替换为man,女生替换为woman

 Python

geder_map = {'男':'man','女':'woman'}
df.性别.map(geder_map)

 

数据合并

  • pandas.merge

merge是pandas中的一种方法,用于将数据框根据某一列或多列合并。

 Python

pandas.merge(left, right, how='inner', on=None)

left、right分别对应需要合并的两个数据框,how表示合并的方式,可选择:inner、outer、left、right,on表示合并数据的参考列,若需根据多列合并数据,以列表形式表示。

应用:生成笛卡尔积:

 Python

df1 = pd.DataFrame({'时间':['2021','2022','2023','2024'],'value':1})
df2 = pd.DataFrame({'地点':['北京','上海'],'value':1})
pd.merge(df1,df2,on='value').drop('value',axis=1)
  • pandas.concat

 Python

pandas.concat(objs, axis=0, join='outer', ignore_index=False)

concat用于将数据框按行或列直接合并。axis=0表示按行合并,列名对齐,axis=1表示按列合并,index对齐。join可选择项有inner和outer,outer保留所有数据,inner只保留交集数据。ignore_index:合成的新数据集是否保留原index。

 Python

df1 = pd.DataFrame({'a':range(5),'b':range(5,10)})
df2 = pd.DataFrame({'a':range(10,15),'b':range(15,20)})
df3 = pd.DataFrame({'c':range(10,16),'d':range(15,21)})
pd.concat([df1,df2],axis=0,ignore_index=True)
pd.concat([df1,df3],axis=1,ignore_index=True,join='inner')
  • append

append为list中的一种方法,向list末尾加入一条数据,注意这里每次将需加入的数据作为一个整体添加到list末尾,如果需要合并两个list,可考虑利用下面+的方法。

 Python

lst1 = list(range(5))
lst2 = list(range(5))
lst1.append(lst2)
  • “+”

+可将两个列表合并。此外+还可以用于连接两个字符串。

 Python

lst1 = list(range(5))
lst2 = list(range(5))
lst1 + lst2
'i'+' '+'love'+' '+'you'

 

缺失值

  • isnull()、notnull()

isnull()、notnull()是pandas中的方法,是用于判断某个位置数据是否为空,一般结合聚合函数使用,能迅速计算出数据的缺失情况。

  • fillna()

 Python

DataFrame.fillna(value=None,inplace=False)

fillna用于填充数据框中的缺失值,value是用于填充的值,inplace表示填充后的数据是否覆盖原数据。

  • dropna()

 Python

DataFrame.dropna(axis=0, how='any', inplace=False)

dropna用于删掉存在缺失值的行,axis表示按行还是按列删除,how表示方法,可选择any、all。inplace表示删除后的数据是否覆盖原数据。

 

横向数据与纵向数据转换

  • pivot_table

将纵表转换为横表,其中index为不需要变动的列的名字,columns为转换为横表后为列名的那一列,values为转换为横表后为值的那一列。

 Python

df.pivot_table(index=,columns=,values=).reset_index() 
  • melt

将横表转换为纵表,其中id_vars为不需要转换的列的名字,var_name为原横表列名转换后的生成的新列列名,value_name为原横表值转换后生成新列的列名。

 Python

df.melt(id_vars=,var_name=,value_name=) 

 

其他

  • pandas.DataFrame.sort_values() 排序
  • list.sort() 排序
  • reset_index() 将index转换为列
  • pandas.DataFrame.drop_duplicates() 删掉重复的数据
  • pandas.DataFrame.drop() 删掉某行或某列
  • pandas.str.slice() 对字符串进行切片
  • pandas.str.split() 按指定字符分割字符串
  • json.loads() json格式数据的读取

你可能感兴趣的