赞
踩
分享一下近期用python做数据清洗汇总的相关代码。不得不说,python代码是真的非常友好,在R上可能就需要写好几句代码才能实现的功能,在python上可能就简单一句话。这里我们用到的python包有pandas、numpy、os等
针对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文件的读取方式。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是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将能实现非常强大的功能,且代码也更加简洁。
例如计算班上男生女生的平均身高与最高身高、最低身高
df.groupby('性别').agg({'身高':['mean','max','min']}).reset_index()
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(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)
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(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为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()是pandas中的方法,是用于判断某个位置数据是否为空,一般结合聚合函数使用,能迅速计算出数据的缺失情况。
DataFrame.fillna(value=None,inplace=False)
fillna用于填充数据框中的缺失值,value是用于填充的值,inplace表示填充后的数据是否覆盖原数据。
DataFrame.dropna(axis=0, how='any', inplace=False)
dropna用于删掉存在缺失值的行,axis表示按行还是按列删除,how表示方法,可选择any、all。inplace表示删除后的数据是否覆盖原数据。
将纵表转换为横表,其中index为不需要变动的列的名字,columns为转换为横表后为列名的那一列,values为转换为横表后为值的那一列。
df.pivot_table(index=,columns=,values=).reset_index()
df.melt(id_vars=,var_name=,value_name=)
pandas.DataFrame.sort_values() 排序
list.sort() 排序
reset_index() 将index转换为列
pandas.DataFrame.drop_duplicates() 删掉重复的数据
pandas.DataFrame.duplicated() 标记重复数据
pandas.DataFrame.drop() 删掉某行或某列
pandas.str.slice() 对字符串进行切片
pandas.str.split() 按指定字符分割字符串
json.loads() json格式数据的读取
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。