Pandas时期:Period
p = pd.Period(2017) print(p) p = pd.Period('2017-1',freq='M') print(p,type(p)) # 通过加减整数可以实现对Period的移动 print(p+1) print(p-1) # 如果两个Period对象拥有相同的频率,则他们的差就是他们之间的单位数量 print(pd.Period('2018-1',freq='M') - p) # period_range函数可用于创建规则的时期范围 rng = pd.period_range('2021-1-1','2021-6-1',freq='M') print(rng) print(pd.Series(np.random.rand(6),rng)) # PeriodIndex类的构造函数允许直接使用一组字符串表示一段时期 values = ['200101','200104','200105'] # 必须指定freq index = pd.PeriodIndex(values,freq='M') print(index) # A-月:每年指定月份的最后一个日历日 p = pd.Period('2022',freq='A-DEC') print(p) # 时期的频率转换asfreq print(p.asfreq('M')) print(p.asfreq('M',how='start')) print(p.asfreq('M',how='end')) print(p.asfreq('H'))
# 时间戳与时期之间的转换:pd.to_period,pd.to_timestamp rng= pd.date_range('2017/1/1',periods=10,freq='M') prng = pd.period_range('2017','2018',freq='M') print(rng) print(prng) ts1 = pd.Series(np.random.rand(len(rng)),index=rng) print(ts1) # 每月的最后一日,转换为每月 # 参数为空,推断每日频率 print(ts1.to_period().head()) print(ts1.to_period('M'))
时间序列-重采样resample
Pandas中的resample,重新采样,是对原样本重新处理的一个方法,是一个对常规时间序列数据重新采样和频率转换的便捷的方法。
重新取样时间序列数据。
方便的时间序列的频率转换和重采样方法。
对象必须具有类似datetime的索引(Datetimelndex、PeriodIndex或Timedeltalndex),或将类似datetime的值传递给on或level关键字。
DataFrame.resample(rule,closed=None,label=None,level=None)
- rule:表示目标转换的偏移量字符串或对象
- closed:在降采样时,各时间段的哪一段是闭合的,‘right’或left’,默认’right’
- label:在降采样时,如何设置聚合值的标签,例如,9:30-9:35会被标记成9∶30还是9:35,默认9:35
rng = pd.date_range('20220101',periods=12) ts = pd.Series(np.arange(1,13),index=rng) print(ts) print('-------------') # 从第一天起0101连续采样五天,并求这五天的和 print(ts.resample('5D').sum(),'->求五天的和\n') print(ts.resample('5D').mean(),'->求五天的平均值\n') print(ts.resample('5D').max(),'->求五天的max\n') print(ts.resample('5D').min(),'->求五天的min\n') print(ts.resample('5D').median(),'->求五天的median\n') print(ts.resample('5D').first(),'->求五天的第一个值\n') print(ts.resample('5D').last(),'->求五天的最后一个值\n') print(ts.resample('5D').ohlc(),'->求五天的OHLC重采样\n')
# 将系列降采样到5天的箱中,但关闭箱间隔的左侧 print(ts.resample('5D',closed='left').sum(),'->left为闭\n') # 将系列降采样到5天的箱中,但关闭箱间隔的右侧 print(ts.resample('5D',closed='right').sum(),'->right为闭\n') #label 聚合值的index,默认取左 # 值采样认为默认(这里closed默认) print(ts.resample('5D',label='left').sum(),'->right\n') print(ts.resample('5D',label='right').sum(),'->rightlabel\n') # 生采样措施 rng = pd.date_range('2017/1/1 0:0:0',periods=5,freq='H') ts = pd.DataFrame(np.arange(15).reshape(5,3), index=rng, columns=['a','b','c'] ) print(ts) print('----低频转高频 主要是如何插值的问题----') print('----asfreq不做填充,返回Nan--------') print(ts.resample('15T').asfreq()) print('----ffill向上填充-------') print(ts.resample('15T').ffill()) print('----bfill向下填充-------') print(ts.resample('15T').bfill())
Pandas文件操作
当使用Pandas做数据分析的时,需要读取事先准备好的数据集,这是做数据分析的第一步。Panda提供了多种读取数据的方法:
read_csv()用于读取文本文件
read_excel(用于读取文本文件
read_json()用于读取json文件
read_sql_query() 读取sql语句
CSV文件读取
CSV又称逗号分隔值文件,是一种简单的文件格式,以特定的结构来排列表格数据。CSV文件能够以纯文本形式存储表格数据,比如电子表格、数据库文件,并具有数据交换的通用格式。CSV文件会在 Excel文件中被打开,其行和列都定义了标准的数据格式。
将CSV中的数据转换为DataFrame对象是非常便捷的。和一般文件读写不一样,它不需要你做打开文件、读取文件、关闭文件等操作。相反,您只需要一行代码就可以完成上述所有步骤,并将数据存储在DataFrarne中。
先介绍常用的属性,name和header
df = pd.read_csv('./16-data/my_csv.csv') print(df,type(df)) print('-----header------') # header 表示使用第几个索引来作为头部信息 # 可以发现原本第一行的数据居然变为了列标签 df = pd.read_csv('16-data/my_csv.csv',header=1) print(df) print('-----name------') # 如果只设置names属性,那么会把你给定的作为列标签,其他的全作为数据输出 df = pd.read_csv('16-data/my_csv.csv',names=['编号','名字','地址','性别','日期']) print(df) print('----name--header----') df = pd.read_csv('16-data/my_csv.csv',names=['编号','名字','地址','性别','日期'],header=0) print(df)
所以names和header的使用场景主要如下:
①. csv文件有表头并且是第一行,那么names和header都无需指定;
②. csv文件有表头、但表头不是第一行,可能从下面几行开始才是真正的表头和数据,这个时候指定header即可;
③. csv文件没有表头,全部是纯数据,那么我们可以通过names手动生成表头;
④. csv文件有表头、但是这个表头你不想用,这个时候同时指定names和header。先用header选出表头和数据,然后再用names将表头替换掉,就等价于将数据读取进来之后再对列名进行rename;
index_col 我们在读取文件之后所得到的DataFrame的索引默认是0、1、2……,我们可以通过set_index设定索引,但是也可以在读取的时候就指定某列为索引。
# index_col把数据中的某一列变为我们的行索引 df = pd.read_csv(r'16-data/students.csv',index_col='birthday') # 还没转换的时候,df的行索引为object类型,而使用df['2002']的方式查找的是列标签,会报错 # print(df['2002']) print(df) print(df.index) print(pd.to_datetime(df.index)) df.index = pd.to_datetime(df.index) # 修改df的时间格式 print(df.index) print(df) print(df['2002']) # 显示生日为2002年的人
这里,我们在读取的时候指定了name列作为索引;此外,除了指定单个列,还可以指定多列作为索引,比如[“id”, “name”]。同时,我们除了可以输入列名外,还可以输入列对应的索引。比如:“id”、“name”、“address”、"date"对应的索引就分别是0、1、2、3。
df2 = pd.read_csv(r'16-data/students.csv',index_col=['gender','birthday']) print(df2) print(df2.loc['女','2004/11/2']) print('------') print(df2.sort_index(inplace=True)) print(df2) print(df2.loc['男'])
usecols 返回列的子集。如果是类似列表的,则所有元素都必须是位置性的(即文档列中的整数索引),或者是与用户在名称中提供的列名或从文档标题行推断的列名相对应的字符串。如果给出了名称,则不考虑文档标题行
pd.read_csv('16-data/students.csv',usecols=['name','birthday','id'],index_col=['id']) # usecols表示读出的数据中只读取useclos中包含的列,不包含的列相当于没有, # 因此如何配合index_col使用,那么就必须在usecols中包含你index_col要使用的列 # 否则报错
encoding 代表编码格式,utf-8,gbk等,也就是以什么编码集去读取文件,默认使用utf-8的方式去读取文件,如果读取文件的格式不为你指定的格式,那么报错UnicodeDecodeError
pd.read_csv('16-data/students_gbk.csv',encoding='GBK')
dtype 在读取数据的时候,设定字段的类型。比如,公司员工的id一般是:00001234,如果默认读取的时候,会显示为1234,所以这个时候要把他转为字符串类型,才能正常显示为00001234:
df = pd.read_csv('16-data/students_step_001.csv',sep='|') print(df) df = pd.read_csv('16-data/students_step_001.csv',sep='|',dtype={'id':str}) print(df)
converters 在读取数据的时候对列数据进行变换,例如将id增加10,但是注意int(x),在使用converters参数时,解析器默认所有列的类型为str,所以需要进行类型转换。
pd.read_csv('16-data/students.csv',converters={'id':lambda x : int(x)+10})
true_values和false_values 指定哪些值应该被清洗为True,哪些值被清洗为False。
这里的替换规则为,只有当某一列的数据类别全部出现在true_values + false_values里面,才会被替换。我们看到"错"并没有被替换成False,原因就是result字段中只有"错"这个类别的值在
true_values + false_values 中,而"对"并没有出现,所以不会替换。而最后的对、错都出现在了true_values + false_values中,所以全部被替换。
print(pd.read_csv('16-data/students.csv',true_values=['男'],false_values=['女'])) print(pd.read_csv('16-data/students.csv',true_values=['女']))
skiprows 表示过滤行,想过滤掉哪些行,就写在一个列表里面传递给skiprows即可。注意的是:这里是先过滤,然后再确定表头,比如:
# 这里把第一行过滤掉了,因为第一行是表头,所以在过滤掉之后第二行就变成表头了。 # 里面除了传入具体的数值,来表明要过滤掉哪些行,还可以传入一个函数。 print(pd.read_csv('16-data/students.csv',skiprows=[0,3])) # 索引从0开始,所以凡是索引大于0、并且%2等于0的记录都过滤掉。索引大于O,是为了保证表头不被过滤掉。 print(pd.read_csv('16-data/students.csv',skiprows=lambda x:x>0 and x%2==0))
skipfooter 从文件末尾过滤行
pandas解析数据时用的引擎,目前解析引擎有两种: c、python。默认为c,因为c引擎解析速度更快,但是特性没有python引擎全
skipfooter接收整型,表示从结尾往上过滤掉指定数量的行,因为引擎退化为python,那么要手动指定engine=“python”,不然会警告。另外需要指定encoding=“utf-8”,因为csv存在编码问题,当引擎退化为python的时候,在Windows上读取会乱码。
print(pd.read_csv('16-data/students.csv',skipfooter=1,encoding='utf-8')) print(pd.read_csv('16-data/students.csv',skipfooter=1,encoding='utf-8',engine='python'))
nrows 设置一次性读入的文件行数,在读入大文件时很有用,比如16G内存的PC无法容纳几百G的大文件。
print(pd.read_csv('16-data/students.csv',nrows=1))
na_values 该参数可以配置那些值需要处理成NaN
print(pd.read_csv('16-data/students.csv',na_values=['女','王杰']))
parse_dates 指定某些列为时间类型,这个参数一般搭配date_parser使用。
date_parser 是用来配合parse_dates参数的,因为有的列虽然是日期,但没办法直接转化,需要我们指定一个解析格式:
import pandas as pd from datetime import datetime df = pd.read_csv('16-data/students.csv',parse_dates=['birthday']) print(df) print('-------------------') print(df.dtypes) # 特别注意默认解析引擎为c,因此如果路径带有中文会报错 要改为使用python df1 = pd.read_csv('16-data/students_年月日1.csv', parse_dates=['birthday'], date_parser=lambda x: datetime.strptime(x,'%Y年%m月%d日'), engine='python') print(df1) print('------------------') print(df1.dtypes)
iterator 迭代器, iterator为 bool类型,默认为False。如果为True,那么返回一个TextFileReader对象,以便逐块处理文件。这个在文件很大、内存无法容纳所有数据文件时,可以分批读入,依次处理。
chunk = pd.read_csv('16-data/students.csv',iterator=True) print(chunk) print(chunk.get_chunk(2)) # 文件还剩下4行 但是我们要读取10行也不会报错 他有多少返回多少 print(chunk.get_chunk(100)) # 但是如果已经读完了还要再读就会报错了 try: chunk.get_chunk(5) except StopIteration as e: print('读取完毕')
chunksize 整型,默认为NOne,设置文件块大小
chunk = pd.read_csv('16-data/students.csv',chunksize=2) print(chunk) print(chunk.get_chunk()) print('-------') print(chunk.get_chunk()) print('--------') print(chunk.get_chunk()) print('读完了还读就报错了') try: print(chunk.get_chunk()) except StopIteration as e: print('已经读完')