pandas统计分析(下)
本文主要介绍使用pandas进行数据移位、数据转换、数据合并、数据导出和日期数据的处理,时间序列等。
数据移位
数据移位就是在分析数据时,需要移动到上一条,在pandas中,可以使用shift方法获得上一条数据。
shift(periods=1, freq=None, axis=0, fill_value=<object object at 0x0000022BE4AA85E0>)
参数:
- periods:表示移动的幅度,可正可负,默认为1。1表示移动一次。这里移动的都是数据,索引不移动,移动之后没有对应值的,赋值为NaN。
- freq:可选参数,默认为None,只适用于时间序列,如果这个参数存在,那么会按照参数值移动时间索引,而数据值没有发生变化。
- axis:axis = 1表示行,axis = 0表示列。默认为0
import pandas as pd
data =[110,105,99,120,115]
index = [1,2,3,4,5]
df = pd.DataFrame(data = data,index = index,columns=['英语'])
df['升降'] = df['英语']-df['英语'].shift()
print(df)
英语 升降
1 110 NaN
2 105 -5.0
3 99 -6.0
4 120 21.0
5 115 -5.0
数据转换
数据转换包括一列数据转多行数据、行列转换、DataFrame转字典,DataFrame转列表,DataFrame转元组
一列数据转多列数据
split方法
pandas中的DataFrame对象中的str.split方法可以实现分割字符串
split(pat=None, n=-1, expand=False)
参数:
- pat:字符串、符合或正则表达式,字符串分割的依据,默认以空格分割字符串
- n:整型,分割次数,默认值是-1,0或1都将返回所有拆分
- expand:布尔型,分割后的结果是否转为DataFrame,默认值是False
- 返回值:系列、索引、DataFrame或多重索引。
import pandas as pd
#导入excel文件指定列数据(‘买家会员名’,‘收货地址’)
df = pd.read_excel('MR/Code/04/26/mrbooks.xls',usecols=['买家会员名','收货地址'])
#使用Split方法分割收货地址
series = df['收货地址'].str.split(' ',expand=True)
df['省'] = series[0]
df['市'] = series[1]
df['区'] = series[2]
df1 = df.head()
买家会员名 | 收货地址 | 省 | 市 | 区 | |
---|---|---|---|---|---|
0 | mr00001 | 重庆 重庆市 南岸区 | 重庆 | 重庆市 | 南岸区 |
1 | mr00003 | 江苏省 苏州市 吴江区 吴江经济技术开发区亨通路 | 江苏省 | 苏州市 | 吴江区 |
2 | mr00004 | 江苏省 苏州市 园区 苏州市工业园区唯亭镇阳澄湖大道维纳阳光花园... | 江苏省 | 苏州市 | 园区 |
3 | mr00002 | 重庆 重庆市 南岸区 长生桥镇茶园新区长电路11112号 | 重庆 | 重庆市 | 南岸区 |
4 | mr00005 | 安徽省 滁州市 明光市 三界镇中心街10001号 | 安徽省 | 滁州市 | 明光市 |
join方法和split方法结合
df = pd.read_excel('MR/Code/04/26/mrbooks.xls',usecols=['买家会员名','宝贝标题'])
df = df.join(df['宝贝标题'].str.split(',',expand=True))
df
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YiykdvDV-1650707196634)(C:\Users\85289\AppData\Roaming\Typora\typora-user-images\image-20220420171419643.png)]
对元组数据进行分割
import pandas as pd
df = pd.DataFrame({'a':[1,2,3,4,5],'b':[(1,2),(3,4),(5,6),(7,8),(9,10)]})
print(df)
a b
0 1 (1, 2)
1 2 (3, 4)
2 3 (5, 6)
3 4 (7, 8)
4 5 (9, 10)
df[['b1','b2']]=df['b'].apply(pd.Series)
print(df)
df = df.join(df['b'].apply(pd.Series))
print(df)
a b b1 b2
0 1 (1, 2) 1 2
1 2 (3, 4) 3 4
2 3 (5, 6) 5 6
3 4 (7, 8) 7 8
4 5 (9, 10) 9 10
a b b1 b2 0 1
0 1 (1, 2) 1 2 1 2
1 2 (3, 4) 3 4 3 4
2 3 (5, 6) 5 6 5 6
3 4 (7, 8) 7 8 7 8
4 5 (9, 10) 9 10 9 10
行列转换
使用stack和unstack及pivot方法进行行列转换或重排。
stack方法是将原来的列索引转换成最内层的行索引,unstack是将最内层的行索引转换成列索引
import pandas as pd
df=pd.read_excel('MR/Code/04/29/grade.xls')
pd.set_option('display.unicode.east_asian_width',True)
df = df.set_index(['班级','序号'])# 设置2级索引‘班级’和‘序号’
df.stack()
print(df)
姓名 得分 排名
班级 序号
1班 1 王*亮 84 11
2 杨** 82 17
3 王*彬 78 37
2班 4 赛*琪 77 51
5 刘** 76 64
6 刘*彤 74 89
3班 7 张*扬 72 115
8 尹** 72 115
9 李*旸 72 115
4班 10 *华煦 72 115
11 于*明 72 115
12 袁*皓 70 151
5班 13 姜* 70 151
14 窦** 68 195
15 张*昕 68 195
pivot方法针对列的值,指定某列的值作为行索引,指定某列的值作为列索引,然后再指定哪些列作为索引对应的值。
pivot(index=None, columns=None, values=None)
df = pd.read_excel('MR/Code/04/31/grade.xls',sheet_name= '英语3')
df1 = df.pivot(index = '序号',columns='班级',values='得分')
df1
班级 | 1班 | 2班 | 3班 | 4班 | 5班 |
---|---|---|---|---|---|
序号 | |||||
1 | 84 | 77 | 72 | 72 | 70 |
2 | 82 | 76 | 72 | 72 | 68 |
3 | 78 | 74 | 72 | 70 | 68 |
DataFrame转换为字典
使用to_dict方法,以索引作为字典的键,列作为字典的值。
import pandas as pd
df = pd.read_excel('MR/Code/04/32/mrbooks.xls')
df1 = df.groupby(['宝贝标题'])['宝贝总数量'].sum().head()
mydict = df1.to_dict()
for i,j in mydict.items():
print(i,':\t',j)
ASP.NET项目开发实战入门全彩版 : 32
ASP.NET项目开发实战入门全彩版,ASP.NET全能速查宝典 : 2
Android学习黄金组合套装 : 4
Android项目开发实战入门 : 1
C#+ASP.NET项目开发实战入门全彩版 : 1
DataFrame转列表
使用tolist转换
import pandas as pd
df = pd.read_excel('MR/Code/04/33/mrbooks.xls')
df1 = df[['买家会员名']].head()
list1 = df1['买家会员名'].values.tolist()
for s in list1:
print(s)
mr00001
mr00003
mr00004
mr00002
mr00005
DataFrame转元组
先通过循环语句按行读取DataFrame数据,然后使用元组函数tuple()将其转换为元组
import pandas as pd
df = pd.read_excel('MR/Code/04/34/fl4.xls')
df1 = df[['label1','label2']].head()
tuples = [tuple(x) for x in df1.values]
for t in tuples:
print(t)
('超巨星', '暗夜比夜星')
('黑矮星', '暗夜比夜星')
('灭霸', '暗夜比夜星')
('亡刃将军', '暗夜比夜星')
('乌木喉', '暗夜比夜星')
excel转换为html网页格式
使用to_html文件转换
import pandas as pd
df = pd.read_excel('MR/Code/04/35/mrbooks.xls')
df.to_html('mrbook.html',header=True,index = False)
数据合并
数据合并主要使用merge和concat方法
merge方法
merge是将两个DataFrame对象列名相同的列进行连接合并,两个DataFrame对象必须具有同名的列。
merge(left, right, how: str = 'inner', on=None, left_on=None, right_on=None, left_index: bool = False, right_index: bool = False, sort: bool = False, suffixes=('_x', '_y'), copy: bool = True, indicator: bool = False, validate=None)
参数说明:
right:合并对象
-
how:合并类型,可以是left、right、outer或inner,默认为inner
- left:只使用来自左数据集的键,类似于sql左外部联接,保留键的顺序
- right:只使用来自右数据集的键,类似于sql右外部联接,保留键的顺序
- outer:使用来自两个数据集的键,类似于sql外部连接,按字典顺序对键进行排序
- inner:使用来自两个数据集的键的交集,类似于sql内部连接,保持左键的顺序
on:标签、列表、数组,默认为None,DataFrame对象连接的列或索引级别名称
left_on:要连接的左数据集的列或索引级名称
right_on:要连接的右数据集的列
left_index:布尔型,使用左数据集的索引作为连接键。如果是多重索引,则其他数据中的键数(索引或列数)必须匹配索引级别数
right_index:布尔型,使用右数据集的索引作为连接键
sort:在合并结果中按照字典顺序对连接键进行排序
suffixes:当左侧数据集和右侧数据集的列名相同时,数据合并后列名将带上'_x'和'_y'后缀
copy:是否复制数据,默认为True
indicator:布尔型或字符串,默认为false
-
validate:字符串,检查合并数据是否为指定类型。
- one_to_one或“1:1”:检查合并键在左右数据集中是否都是唯一的
- one_to_many或“1:m”:检查合并键在左数据集中是否都是唯一的
- many_to_one或“m:1”:检查合并键在右数据集中是否都是唯一的
- many_to_many或“m:m”:允许但不检查
-
返回值:DataFrame对象,两个合并对象的数据集
常规合并
import pandas as pd df1 =pd.DataFrame({'编号':['mr001','mr002','mr003'], '语文':[110,105,109], '数学':[105,88,120], '英语':[99,115,130]}) df2 = pd.DataFrame({'编号':['mr001','mr002','mr003'], '体育':[34.5,39.7,38]}) df_merge = pd.merge(df1,df2,on = '编号') print(df_merge)
编号 语文 数学 英语 体育 0 mr001 110 105 99 34.5 1 mr002 105 88 115 39.7 2 mr003 109 120 130 38.0
df_merge = pd.merge(df1,df2,right_index=True,left_index=True)
print(df_merge)
编号_x 语文 数学 英语 编号_y 体育
0 mr001 110 105 99 mr001 34.5
1 mr002 105 88 115 mr002 39.7
2 mr003 109 120 130 mr003 38.0
df_merge = pd.merge(df1,df2,on = '编号',how = 'left')
print(df_merge)
编号 语文 数学 英语 体育
0 mr001 110 105 99 34.5
1 mr002 105 88 115 39.7
2 mr003 109 120 130 38.0
多对一的数据合并
多对一是指两个数据集的共有列中的数据不是一对一的关系
df2 =pd.DataFrame({'编号':['mr001','mr001','mr003'],
'语文':[110,105,109],
'数学':[105,88,120],
'英语':[99,115,130],
'时间':['1月','2月','1月']})
df1 = pd.DataFrame({'编号':['mr001','mr002','mr003'],
'学生姓名':['a','b','c']})
df_merge = pd.merge(df1,df2,on ='编号')
print(df_merge)
编号 学生姓名 语文 数学 英语 时间
0 mr001 a 110 105 99 1月
1 mr001 a 105 88 115 2月
2 mr003 c 109 120 130 1月
多对多的数据合并
多对多是指两个数据集的共有列中的数据不全是一对一的关系,都有重复数据。
#合并数据并相互补全
import pandas as pd
df1 = pd.DataFrame({'编号':['mr001','mr002','mr003','mr001','mr001'],
'体育':[34.5,39.7,38,33,35]})
df2 = pd.DataFrame({'编号':['mr001','mr002','mr003','mr003','mr003'],
'语文':[110,105,109,110,108],
'数学':[105,88,120,123,119],
'英语':[99,115,130,109,128]})
df_merge=pd.merge(df1,df2)
print(df_merge)
编号 体育 语文 数学 英语
0 mr001 34.5 110 105 99
1 mr001 33.0 110 105 99
2 mr001 35.0 110 105 99
3 mr002 39.7 105 88 115
4 mr003 38.0 109 120 130
5 mr003 38.0 110 123 109
6 mr003 38.0 108 119 128
concat方法
concat(objs: Union[Iterable[ForwardRef('NDFrame')], Mapping[Union[Hashable, NoneType], ForwardRef('NDFrame')]], axis=0, join='outer', ignore_index: bool = False, keys=None, levels=None, names=None, verify_integrity: bool = False, sort: bool = False, copy: bool = True)
参数:
- objs:Series、DataFrame或panel对象的序列或映射。如果传入一个字典,则排序的键将用作键参数
- axis:
- join:值为inner(内连接)或outer(外连接),处理其他轴上的索引方式。默认为outer
- ignore_index:布尔值,默认为false,保留索引
- keys:序列,默认为none。使用传递的键作为最外层构建层次索引。如果为多索引,应该使用元组
- levels:序列列表,默认为none。用于构建multiindex的特定级别(唯一值);否则,他们将从键推断
- names:list列表,默认为none,结果层次索引中的级别的名称
相同字段的表首位连接
表结构相同的数据直接合并,表首尾相接
dfs = [df1,df2,df3]
result = pd.concat(dfs)
result = pd.concat(dfs,keys = ['1月','2月','3月'])
横向表合并(行对齐)
当合并的数据列名称不一致,可以设置参数,concat()方法将按行对齐,然后将不同列名的两组数据进行合并,缺失的用NaN填充
result = pd.concat([df1,df4],axis = 1)
交叉合并
交叉合并需要在代码中加上join参数,值为inner,则为两张表的交集,为outer,则为两张表的并集。
result = pd.concat([df1,df4],axis = 1,join = 'inner')
指定表对齐数据(行对齐)
如果指定参数join_axes,就可以指定根据哪张表来对齐数据。
result = pd.concat([df1,df4],axis = 1,join_axis = [df4.index])
数据导出
导出为excel文件
使用to_excel方法
to_excel(excel_writer, sheet_name: 'str' = 'Sheet1', na_rep: 'str' = '', float_format: 'Optional[str]' = None, columns=None, header=True, index=True, index_label=None, startrow=0, startcol=0, engine=None, merge_cells=True, encoding=None, inf_rep='inf', verbose=True, freeze_panes=None, storage_options: 'StorageOptions' = None)
df_merge.to_excel('merge.xlsx')
df1.to_excel('df1.xlsx',sheet_name='df1')
导出为csv文件
to_csv(path_or_buf: 'Optional[FilePathOrBuffer]' = None, sep: 'str' = ',', na_rep: 'str' = '', float_format: 'Optional[str]' = None, columns: 'Optional[Sequence[Label]]' = None, header: 'Union[bool_t, List[str]]' = True, index: 'bool_t' = True, index_label: 'Optional[IndexLabel]' = None, mode: 'str' = 'w', encoding: 'Optional[str]' = None, compression: 'CompressionOptions' = 'infer', quoting: 'Optional[int]' = None, quotechar: 'str' = '"', line_terminator: 'Optional[str]' = None, chunksize: 'Optional[int]' = None, date_format: 'Optional[str]' = None, doublequote: 'bool_t' = True, escapechar: 'Optional[str]' = None, decimal: 'str' = '.', errors: 'str' = 'strict', storage_options: 'StorageOptions' = None)
df.to_csv('Result.csv')
#分隔符
df.to_csv('result.csv',sep='?')
#替换空值
df.to_csv('result.csv',na_rep='NA')
#格式化数据,保留两位小数
df.to_csv('result.csv',float_format='%.2f')
# 保留某列数据,保存索引列和name列
df.to_csv('result.csv',columns=['name'])
#是否保留列名,不保留列名
df.to_csv('result.csv',header=True)
#是否保留行索引,不保留行索引
df.to_csv('result.csv',index = False)
导出多个sheet
导出多个sheet,首先使用pd.ExcelWriter方法打开一个excel文件,然后使用to_excel方法导出指定的sheet
df1.to_excel('df1.xlsx',name = 'df1')
work = pd.ExcelWriter('df2.xlsx')
df1.to_excel(work,sheet_name='df2')
df1['A'].to_excel(work,sheet_name='df3')
work.save()
日期数据处理
DataFrame的日期转换
日常工作中,日期格式的表达有很多种,我们可以通过pandas中的to_datetime方法来批量出路日期数据转换。
to_datetime(arg: Union[~DatetimeScalar, List, Tuple, ~ArrayLike, ForwardRef('Series')], errors: str = 'raise', dayfirst: bool = False, yearfirst: bool = False, utc: Union[bool, NoneType] = None, format: Union[str, NoneType] = None, exact: bool = True, unit: Union[str, NoneType] = None, infer_datetime_format: bool = False, origin='unix', cache: bool = True)
import pandas as pd
df = pd.DataFrame({'原日期':['14-Feb-20','02/14/2020',
'2020.02.14','20200214']})
df['转换后的日期'] = pd.to_datetime(df['原日期'])
print(df)
import pandas as pd
df = pd.DataFrame({'原日期':['14-Feb-20','02/14/2020',
'2020.02.14','20200214']})
df['转换后的日期'] = pd.to_datetime(df['原日期'])
print(df)
原日期 转换后的日期
0 14-Feb-20 2020-02-14
1 02/14/2020 2020-02-14
2 2020.02.14 2020-02-14
3 20200214 2020-02-14
将一组数据组合为日期数据
import pandas as pd
df= pd.DataFrame({'year':[2018,2019,2020],
'month':[1,3,2],
'day':[4,5,14],
'hour':[13,8,2],
'minute':[23,12,14],
'second':[2,4,0]}
)
df['组合后的日期'] = pd.to_datetime(df)
print(df)
year month day hour minute second 组合后的日期
0 2018 1 4 13 23 2 2018-01-04 13:23:02
1 2019 3 5 8 12 4 2019-03-05 08:12:04
2 2020 2 14 2 14 0 2020-02-14 02:14:00
dt对象的使用
dt对象是Series对象中用于获取日期属性的一个访问器对象,可以获取日期中的年、月、日、星期数、季节等,还可以判断日期是否处在年底。
Series.dt()
#获取年、月、日
df['年'],df['月'],df['日']=df['日期'].dt.year,df['日期'].dt.month,df['日期'].dt.day
#获取星期几
df['星期几']=df['日期'].dt.day_name()
#判断所处季度
df['季度']=df['日期'].dt.quarter
是否为年底最后一天
df['是否年底']=df['日期'].dt.is_year_end
import pandas as pd
df=pd.DataFrame({'原日期':['2019.1.05', '2019.2.15', '2019.3.25','2019.6.25','2019.9.15','2019.12.31']})
df['日期']=pd.to_datetime(df['原日期'])
df['年'],df['月'],df['日'] = df['日期'].dt.year,df['日期'].dt.month,df['日期'].dt.day
df['星期几'] = df['日期'].dt.day_name()
df['季度'] = df['日期'].dt.quarter
df['是否年底'] = df['日期'].dt.is_year_end
print(df)
原日期 日期 年 月 日 星期几 季度 是否年底
0 2019.1.05 2019-01-05 2019 1 5 Saturday 1 False
1 2019.2.15 2019-02-15 2019 2 15 Friday 1 False
2 2019.3.25 2019-03-25 2019 3 25 Monday 1 False
3 2019.6.25 2019-06-25 2019 6 25 Tuesday 2 False
4 2019.9.15 2019-09-15 2019 9 15 Sunday 3 False
5 2019.12.31 2019-12-31 2019 12 31 Tuesday 4 True
获取日期区间的数据
获取日期区间的数据方法是直接在DataFrame中输入日期或日期区间,但前提是必须设置日期为索引。
import pandas as pd
df = pd.read_excel('MR/Code/04/47/mingribooks.xls')
df1 = df[['订单付款时间','买家会员名','联系手机','买家实际支付金额']]
df1 = df1.sort_values(by = ['订单付款时间'])
df1 = df1.set_index('订单付款时间')# 将日期设置为索引
#获取某个区间数据
df2 = df1['2018-05-11':'2018-06-10']
df2
买家会员名 | 联系手机 | 买家实际支付金额 | |
---|---|---|---|
订单付款时间 | |||
2018-05-11 11:37:00 | mrhy61 | 1********** | 55.86 |
2018-05-11 13:03:00 | mrhy80 | 1********** | 268.00 |
2018-05-11 13:27:00 | mrhy40 | 1********** | 55.86 |
2018-05-12 02:23:00 | mrhy27 | 1********** | 48.86 |
2018-05-12 21:13:00 | mrhy76 | 1********** | 268.00 |
... | ... | ... | ... |
2018-06-09 21:17:00 | yhhy47 | 1*********** | 43.86 |
2018-06-09 22:42:00 | yhhy6 | 1*********** | 167.58 |
2018-06-10 08:22:00 | yhhy4 | 1*********** | 166.43 |
2018-06-10 09:06:00 | yhhy14 | 1*********** | 137.58 |
2018-06-10 21:11:00 | yhhy24 | 1*********** | 139.44 |
按不同时期统计并显示数据
按时期统计数据
主要通过DataFrame对象的resample()方法结合数据计算函数实现。resample方法主要应用于时间序列频率转换和重采样。它可以从日期中获取年、月、日、星期、季节等,再结合数据计算函数就可以实现按照不同时期统计数据。
df1 = =df1.resample('AS').sum()#年
df1 = =df1.resample('Q').sum()#季度
df1 = =df1.resample('M').sum()#月
df1 = =df1.resample('W').sum()#星期
df1 = =df1.resample('D').sum()#天
resample函数要求索引项必须为日期型,可以使用如下代码转换
df1.index = pd.to_datetime(df1.index)
按时期显示数据
使用to_period()方法将时间转换为时期,从而实现按时期显示数据,日期必须设置为索引列。
to_period(freq=None, axis: 'Axis' = 0, copy: 'bool' = True)
参数:
- freq:字符串,周期索引的频率,默认为None
- axis:行列索引,axis = 0表示行索引,1表示列索引
- copy:是否复制数据,默认为True
- 返回值:带周期索引的时间序列
df1.to_period('A')#按年
df1.to_period('Q')#按季度
df1.to_period('M')#按月
df1.to_period('W')#按星期
按时期统计并显示数据
df2.resample('AS').sum().to_period('A')#按年统计数据
df2.resample('Q').sum().to_period('Q')#按季度统计数据
df2.resample('M').sum().to_period('M')#按月统计数据
df2.resample('W').sum().to_period('W')#按星期统计数据
时间序列
重采样(resample方法)
在pandas中对时间序列的频率的调整成为重新采样,即将时间序列从一个频率转换到另一个频率的处理过程。resample方法对常规时间序列重新采样和频率转换,包括降采样和升采样两种。
resample(rule, axis=0, closed: 'Optional[str]' = None, label: 'Optional[str]' = None, convention: 'str' = 'start', kind: 'Optional[str]' = None, loffset=None, base: 'Optional[int]' = None, on=None, level=None, origin: 'Union[str, TimestampConvertibleTypes]' = 'start_day', offset: 'Optional[TimedeltaConvertibleTypes]' = None)
参数说明:
- rule:字符串,偏移量表示目标字符串或对象转换。
- how:用于产生聚合值的函数名或数组函数
- axis:axis= 0 表示列,axis= 1表示行
- fill_method:升采样时所使用的填充方法,ffill(用前值填充)或bfill方法(用后值填充)
- closed:降采样时,时间区间的开闭,其值为left或right,left(左闭右开),right(左开右闭),默认为right
- label:降采样时,如何设置聚合之的标签
- convention:当重采样时,将低频率转换为高频率时所采用的约定,其值为start或end,默认为start
- kind:聚合到时期(period)或时间戳(timestamp),默认聚合到时间序列的索引类型
- loffset:聚合标签的时间校正值,默认为None
- limit:向前或向后填充时,允许填充的最大时期数,默认为None
- base:整型,默认为0.对于均匀细分1天的频率,聚合间隔的‘原点’
- on:字符串,可选参数,默认为None。对DataFrame对象使用列代替索引进行重新采样。列必须与日期时间类似
- level:字符串或整型,可选参数,默认为None。用于多索引,重新采样的级别名称或级别编号,级别必须与日期时间类似。
- 返回值:重新采样对象
一分钟的时间序列转换为3分钟的时间序列
import pandas as pd
index = pd.date_range('02/02/2020',periods=9,freq= 'T')
series = pd.Series(range(9),index = index)
print(series)
print(series.resample('3T').sum())
2020-02-02 00:00:00 0
2020-02-02 00:01:00 1
2020-02-02 00:02:00 2
2020-02-02 00:03:00 3
2020-02-02 00:04:00 4
2020-02-02 00:05:00 5
2020-02-02 00:06:00 6
2020-02-02 00:07:00 7
2020-02-02 00:08:00 8
Freq: T, dtype: int64
2020-02-02 00:00:00 3
2020-02-02 00:03:00 12
2020-02-02 00:06:00 21
Freq: 3T, dtype: int64
降采样处理
降采样是按照周期由高频率转向低频率。如将5min采样时间变为一天
降采样会涉及数据的聚合
import pandas as pd
df = pd.read_excel('MR/Code/04/50/time.xls')
df1 = df.set_index('订单付款时间')
print(df1.resample('W').sum().head())
买家实际支付金额 宝贝总数量
订单付款时间
2018-01-07 5735.91 77
2018-01-14 4697.62 70
2018-01-21 5568.77 74
2018-01-28 5408.68 53
2018-02-04 1958.19 19
升采样处理
升采样时周期由低频率转向高频率,将数据从低频率转换到高频率时,就不需要聚合了,将其重采样到日频率,默认会引入缺失值
升采样涉及到数据的填充,根据填充的方法不同,填充的数据也不同。
- 不填充:空值用NaN代替,使用asfreq()方法
- 用前值填充。用前面的值填充空值,使用ffill或pad,可以使用字母f代替。
- 用后值填充,使用bfill方法,可以使用字母b代替。
import pandas as pd
import numpy as np
rng = pd.date_range('20200202',periods=2)
s1 = pd.Series(np.arange(1,3),index = rng)
s1_6h_asfreq = s1.resample('6H').asfreq()
print(s1_6h_asfreq)
s1_6h_pad = s1.resample('6H').pad()
print(s1_6h_pad)
s1_6h_ffill = s1.resample('6H').ffill()
print(s1_6h_ffill)
s1_6h_bfill = s1.resample('6H').bfill()
print(s1_6h_bfill)
2020-02-02 00:00:00 1.0
2020-02-02 06:00:00 NaN
2020-02-02 12:00:00 NaN
2020-02-02 18:00:00 NaN
2020-02-03 00:00:00 2.0
Freq: 6H, dtype: float64
2020-02-02 00:00:00 1
2020-02-02 06:00:00 1
2020-02-02 12:00:00 1
2020-02-02 18:00:00 1
2020-02-03 00:00:00 2
Freq: 6H, dtype: int32
2020-02-02 00:00:00 1
2020-02-02 06:00:00 1
2020-02-02 12:00:00 1
2020-02-02 18:00:00 1
2020-02-03 00:00:00 2
Freq: 6H, dtype: int32
2020-02-02 00:00:00 1
2020-02-02 06:00:00 2
2020-02-02 12:00:00 2
2020-02-02 18:00:00 2
2020-02-03 00:00:00 2
Freq: 6H, dtype: int32
时间序列数据汇总(ohlc函数)
使用ohlc函数可以得到金融领域的开始值(open)、结束值(close)、最高值(high)和最低值(low)
import pandas as pd
import numpy as np
rng = pd.date_range('2/2/2020',periods=12,freq = 'T')
s1 = pd.Series(np.arange(12),index = rng)
print(s1.resample('5min').ohlc())
open high low close
2020-02-02 00:00:00 0 4 0 4
2020-02-02 00:05:00 5 9 5 9
2020-02-02 00:10:00 10 11 10 11
移动窗口数据计算(rolling函数)
由于时点的数据波动较大,某一点的数据就不能很好的表现它本身的特性,于是就有了“移动窗口”的概念,简单的说,为了提升数据的可靠性,将某个点的取值扩大到包含这个点的一段区间,用区间进行判断,这个区间就是窗口。
rolling(window: 'Union[int, timedelta, BaseOffset, BaseIndexer]', min_periods: 'Optional[int]' = None, center: 'bool_t' = False, win_type: 'Optional[str]' = None, on: 'Optional[str]' = None, axis: 'Axis' = 0, closed: 'Optional[str]' = None)
参数:
- window:时间窗口的大小,有两种形式,即int或offset。如果使用int,则数值表示计算统计量的观测值的数量,即向前几个数据;如果使用offset,则表示时间窗口的大小。
- min_periods:每个窗口最少包含的观测值数量,小于这个值的窗口结果为NA。值可以是int,默认值为None。offset情况下,默认值为1
- center:吧窗口的标签设置为居中,默认为false,居右
- win_type:窗口的类型。截取窗的各种函数。
- on:可选参数
- axis:axis= 0列,默认列
- closed:定义区间的开闭
- 返回值:为特定操作而生成的窗口或移动窗口子类。
import pandas as pd
index = pd.date_range('20200201','20200215')
data = [3,6,7,4,2,1,3,8,9,10,12,15,13,22,14]
s1_data = pd.Series(data,index = index)
print(s1_data)
s1_data.rolling(3).mean()
2020-02-01 3
2020-02-02 6
2020-02-03 7
2020-02-04 4
2020-02-05 2
2020-02-06 1
2020-02-07 3
2020-02-08 8
2020-02-09 9
2020-02-10 10
2020-02-11 12
2020-02-12 15
2020-02-13 13
2020-02-14 22
2020-02-15 14
Freq: D, dtype: int64
2020-02-01 NaN
2020-02-02 NaN
2020-02-03 5.333333
2020-02-04 5.666667
2020-02-05 4.333333
2020-02-06 2.333333
2020-02-07 2.000000
2020-02-08 4.000000
2020-02-09 6.666667
2020-02-10 9.000000
2020-02-11 10.333333
2020-02-12 12.333333
2020-02-13 13.333333
2020-02-14 16.666667
2020-02-15 16.333333
Freq: D, dtype: float64
s1_data.rolling(3,min_periods=1).mean()
2020-02-01 3.000000
2020-02-02 4.500000
2020-02-03 5.333333
2020-02-04 5.666667
2020-02-05 4.333333
2020-02-06 2.333333
2020-02-07 2.000000
2020-02-08 4.000000
2020-02-09 6.666667
2020-02-10 9.000000
2020-02-11 10.333333
2020-02-12 12.333333
2020-02-13 13.333333
2020-02-14 16.666667
2020-02-15 16.333333
Freq: D, dtype: float64
综合应用
excel多表合并
import pandas as pd
import glob
filearray = []
filelocation = glob.glob(r'MR/Code/04/example/01/aa/*.xlsx')#指定目录下所有的excel文件
# 遍历指定目录
for filename in filelocation:
filearray.append(filename)
print(filename)
res = pd.read_excel(filearray[0])#读取第一个excel文件
#顺序读取excel文件并进行合并
for i in range(1,len(filearray)):
A = pd.read_excel(filearray[i])
res = pd.concat([res,A],ignore_index=True,sort = False)
print(res.index)
#写入excel文件,并保持
writer = pd.ExcelWriter('all.xlsx')
res.to_excel(writer,'sheet1')
writer.save()
股票行情数据分析
股票数据包括开盘价、收盘价、最高价、最低价、成交量等多个指标。收盘价是当日行情的标准,也是下一个交易日开盘价的依据,可以预测未来证券市场行情,因此一般采用收盘价作为计算依据。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
aa = r'MR/Code/04/example/02/000001.xlsx'
df = pd.DataFrame(pd.read_excel(aa))
df['date']= pd.to_datetime(df['date'])#将数据类型转换为日期类型
df = df.set_index('date')#将date设置为index
df = df[['close']]
df['20天'] = np.round(df['close'].rolling(window= 20,center = False).mean(),2)
df['50天'] = np.round(df['close'].rolling(window= 50,center = False).mean(),2)
df['200天'] = np.round(df['close'].rolling(window= 200,center = False).mean(),2)
plt.rcParams['font.sans-serif']=['SimHei']# 解决中文乱码
df.plot(secondary_y = ['收盘价','20','50','200'],grid = True)
plt.legend(('收盘价','20天','50天','200天'),loc = 'upper right')