使用python数据清洗代码实例
作者:dogyii
数据读入与写出
csv
针对csv格式的数据,最简单的一种方法是用pandas中的read_csv方法,具体代码如下。其中第一个参数为待读入数据的路径,一个实用小技巧为./
表示当前文件夹,../
表示上层文件夹。这样如果待读入文件与代码文件在同一个文件夹下,可以节省掉很多层文件路径的输入。另外两个我较常用的参数为encoding和sep,其中encoding可指定数据UTF编码,sep为指定数据分隔符,默认为,
,但我经常遇到以\t
为分隔符的数据。如果你遇到了类似这样的报错ParserError: Error tokenizing data. C error: Expected 1 fields in line 57, saw 3
,可以考虑下是不是分隔符不对。
import pandas as pd pd.read_csv('*.csv',encoding='gbk',sep='\t')
此外,有时候一个文件太大。其分别存储在不同文件中,甚至分开存储在不同文件夹下,这时就需考虑批量读取了。 在展示代码前,先介绍一下数据背景。现在我有一个叫obj的文件夹,其中存储了一系列以’job_id='开头的文件夹,在每个文件夹中又存储了一系列以’job_id='开头的csv的文件。这些文件存储的都是同一种数据,目前我的任务是读入这一批数据,并合并成一个数据框。
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编码。
df.to_csv('./*.csv',index=False,encoding='gbk)
txt
介绍一个txt文件的读取方式。file_name为文件路径,使用with open as则在数据读入结束后能自动关闭文件夹节约内存,推荐使用这种方式。readlines自动按行读取所有文件,以列表返回,此外还可以选择realine:一次读取一行文件,read:以一个字符串读取所有文件。
with open(file_name) as file: for line in file.readlines(): pass
这里返回的每一行数据(line),是以字符串的形式返回的,可考虑将字符串进行处理,提取需要的信息。这里介绍几个好用的字符串函数:当使用readlines时,每行数据末尾以\n
结束,line.rstrip()
:删除 string 字符串末尾的指定字符,若没有指定。默认删除空格,tab,跨行符。 line.split()
:按指定字符分割字符串,并以列表的形式返回。
数据清洗
时间处理
- 时间的加减
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:将时间格式转换为字符串。
- 显示给定时间为周几
如果是数据框,可使用如下代码:
df = pd.DataFrame({'day':['2021-11-12','2021-11-13','2021-11-14']}) pd.to_datetime(df.day).dt.weekday+1
可看出如上日期分别对应周五、周六、周天
- 给定日期,显示为一年中的第几周。
pd.to_datetime('2021-11-12').isocalendar()[1]
isocalendar()
返回时间所处的年份,以及该年的第几周,为周几,其结果对应的第二个位置,即为第几周。
- 生成时间上的等差数列
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中非常好用的一个函数,其主要功能是将数据框按某一特征分组。结合相关聚合函数,能非常迅速地计算出需要的指标。 例如计算某班上男生和女生的平均身高:
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将能实现非常强大的功能,且代码也更加简洁。
例如计算班上男生女生的平均身高与最高身高、最低身高
df.groupby('性别').agg({'身高':['mean','max','min']}).reset_index()
- apply
apply函数可对数据框的行或列应用指定的方法,并返回值,默认为行。
- 常用聚合函数
value_counts
:对某一离散变量不同类别计数,默认对缺失值不计数。count
:统计非缺失值个数。mean
:求均值median
:求中位数max
:求最大值min
:求最小值quantile
:求分位数
批量操作
- 列表解析式
如若需要对列表的每一个元素进行操作,并返回同样大小的列表,可考虑使用列表解析器,例如对某元素进行向上取整:
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可将其转换为列表。同样对某元素进行向上取整:
list(map(math.ceil,lst))
另外还有一个map是pandas包中的map函数,功能上与上述map方法类似。此外其还有一个很好用的替换功能。例如将上面身高数据中,男生替换为man,女生替换为woman
geder_map = {'男':'man','女':'woman'} df.性别.map(geder_map)
数据合并
- pandas.merge
merge是pandas中的一种方法,用于将数据框根据某一列或多列合并。
pandas.merge(left, right, how='inner', on=None)
left、right分别对应需要合并的两个数据框,how表示合并的方式,可选择:inner、outer、left、right,on表示合并数据的参考列,若需根据多列合并数据,以列表形式表示。
应用:生成笛卡尔积:
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
pandas.concat(objs, axis=0, join='outer', ignore_index=False)
concat用于将数据框按行或列直接合并。axis=0表示按行合并,列名对齐,axis=1表示按列合并,index对齐。join可选择项有inner和outer,outer保留所有数据,inner只保留交集数据。ignore_index:合成的新数据集是否保留原index。
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,可考虑利用下面+
的方法。
lst1 = list(range(5)) lst2 = list(range(5)) lst1.append(lst2)
“+”
+
可将两个列表合并。此外+
还可以用于连接两个字符串。
lst1 = list(range(5)) lst2 = list(range(5)) lst1 + lst2 'i'+' '+'love'+' '+'you'
缺失值
- isnull()、notnull()
isnull()、notnull()是pandas中的方法,是用于判断某个位置数据是否为空,一般结合聚合函数使用,能迅速计算出数据的缺失情况。
- fillna()
DataFrame.fillna(value=None,inplace=False)
fillna用于填充数据框中的缺失值,value是用于填充的值,inplace表示填充后的数据是否覆盖原数据。
- dropna()
DataFrame.dropna(axis=0, how='any', inplace=False)
dropna用于删掉存在缺失值的行,axis表示按行还是按列删除,how表示方法,可选择any、all。inplace表示删除后的数据是否覆盖原数据。
横向数据与纵向数据转换
- pivot_table
将纵表转换为横表,其中index为不需要变动的列的名字,columns为转换为横表后为列名的那一列,values为转换为横表后为值的那一列。
df.pivot_table(index=,columns=,values=).reset_index()
- melt
将横表转换为纵表,其中id_vars为不需要转换的列的名字,var_name为原横表列名转换后的生成的新列列名,value_name为原横表值转换后生成新列的列名。
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格式数据的读取
到此这篇关于使用python数据清洗代码实例的文章就介绍到这了,更多相关python数据清洗代码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!