Pandas统计分析(数据转换、合并、日期数据处理、时间序列)

458 阅读21分钟

数据转换

数据转换一般包括一列数据转换为多列数据、行列转换、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('mrbooks.xls',usecols=['买家会员名','收货地址']) #只使用【买家会员名】和【收割地址】这两列
print(df)
#使用split方法分割“收货地址”
series=df['收货地址'].str.split(' ',expand=True) #expand=True转为DataFrame对象
print(series)
df['省']=series[0]
df['市']=series[1]
df['区']=series[2]
df1=df.head()
print(df1)

join()方法与split()方法结合

import pandas as pd

#导入Excel文件部分列数据(“买家会员名”和“宝贝标题”)
df = pd.read_excel('mrbooks.xls',usecols=['买家会员名','宝贝标题'])
#使用join方法和split方法分割“宝贝标题”
df = df.join(df['宝贝标题'].str.split(',', expand=True))
df1=df.head()
print(df1)

对元组数据进行分割

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)

# apply函数分割元组
df[['b1', 'b2']] = df['b'].apply(pd.Series)
print(df)

#或者join方法结合apply函数分割元组
df= df.join(df['b'].apply(pd.Series))
print(df)

输出结果:

image.png

行列转换

在pandas处理数据过程中,有时需要对数据进行行列转换或重排,主要使用stack()方法、unstack()方法和pivot()函数。

stack()方法

stack方法用于将原来的列索引转换成最内层的行索引。如下图所示。

image.png

语法如下:

DataFrmae.stack(level=1,dropna=True)

参数说明:

level:索引层级,定义为一个索引或者标签,或索引或标签列表,默认值是-1。

dropna:布尔型,默认值是True,

import pandas as pd

df=pd.read_excel('grade.xls')      #导入Excel文件
df = df.set_index(['班级','序号']) #设置2级索引“班级”和“序号”
df = df.stack()
print(df)

unstack()方法

unstack方法与stack方法相反,他是stack方法的逆操作,即将最内层的行索引转换成列索引。如下图所示。

image.png

语法如下:

DataFrame.unstack(level=1-1,fill_value=None)

参数如下:

levle: 索引层级,定义为一个索引或标签,或索引或列表标签,默认值为-1。

fill_value:整型、字符串或字典。如果unstack()方法产生丢失值,则用这个值替换NaN。

import pandas as pd
#设置数据显示的列数和宽度
pd.set_option('display.max_columns',500)
pd.set_option('display.width',1000)
#解决数据输出时列名不对齐的问题
pd.set_option('display.unicode.east_asian_width', True)
df=pd.read_excel('grade.xls',sheet_name='英语2')      #导入Excel文件
df = df.set_index(['班级','序号','Unnamed: 2'])       #设置多级索引
print(df.unstack())

pivot方法

pivot()方法针对列的值,即指定某列的值作为行索引,指定某列的值作为列索引,然后再指定那些列作为索引对应的值。unstack针对索引进行操作,pivot针对值进行操作。但二者的功能实际上可以相互实现。

语法如下:

DataFrame.pivot(index=None,columns=None,values=None)

参数说明:

index:字符串或对象,可选参数。列用于创建新Datafrmae数据的索引。如果没有,则使用现有索引。

columns:字符串或对象,列用于创建新DataFrame的列。

values:列用于填充新Dataframe的值,如果未指定,则将使用所有剩余的列,结果将具有分层索引列。

import pandas as pd

df=pd.read_excel('grade.xls',sheet_name='英语3')      #导入Excel文件
df1=df.pivot(index='序号',columns='班级',values='得分')
print(df1)

image.png

DataFrame转换为字典

DataFrame转换为字典,主要使用to_dict()方法,以索引作为字典的键,以列作为字典的值。

import pandas as pd
df = pd.read_excel('mrbooks.xls')
df1=df.groupby(["宝贝标题"])["宝贝总数量"].sum().tail()  #查看后5条数据

mydict=df1.to_dict()    #DataFrame转字典
for i,j in mydict.items():
    print(i,':\t', j)

DataFrame转换为列表

DataFrame转换为列表,主要使用tolist()方法。

import pandas as pd
df =pd.read_excel('mrbooks.xls')
df1=df[['买家会员名']].head()
print(df1)
list1=df1['买家会员名'].values.tolist()   #数组转列表
for s in list1:
    print(s)

注意:

对于一个dataframe类型的数据,可以用[]和[[]]来取其某一列或某几列(仅限[[]]才能取某几列)。

从[]只能取某一列就能看出,这个取出来的是Series对象,而[[]]取出来的是DataFrame类型的。

import pandas as pd
df =pd.read_excel('mrbooks.xls')
df1=df['买家会员名'].head()
df2=df[['买家会员名']].head()
print(df1)
print(df2)

image.png

DataFrame转换为元祖

DataFrame转换为元组,首先通过循环语句按行读取DataFrame数据,然后使用元组函数tuple()将其转换为元组。

import pandas as pd
df = pd.read_excel('fl4.xls')
df1=df[['label1','label2']].head()
tuples = [tuple(x) for x in df1.values]
for t in tuples:
    print(t)
    
#注意,这两种写法意思一致
import pandas as pd
df = pd.read_excel('fl4.xls',usecols=['label1','label2'])
df1=df.head()
print(df1)
tuples = [tuple(x) for x in df1.values]
for t in tuples:
    print(t)

Excel转换为HTML网页格式

excel转为html,使用的是to_html()

import pandas as pd
df=pd.read_excel('mrbooks.xls',usecols=['买家会员名','宝贝标题']).head()
df.to_html('mrbooks.html',header = True,index = False,encoding='gbk')

数据合并(merge()方法) pandas模块中的merge()方法是按照两个DataFrame对象列名相同的列进行连接合并,两个对象必须具有相同名的列。 语法如下:

pandas.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)

常用参数说明:

  • left 和 right: 要合并的左侧和右侧 DataFrame。

  • on: 指定用于合并的列名或列名列表。默认为 None。如果指定了列名或列名列表,则只有这些列匹配的行才会被合并。

  • how: 指定合并方式的字符串,包括 'inner'、'outer'、'left' 和 'right'。默认为 'inner'。具体含义如下:

    • 'inner': 只保留两个 DataFrame 中都存在的行。
    • 'outer': 保留两个 DataFrame 的所有行,并在缺失数据的位置填充 NaN。
    • 'left': 保留左侧 DataFrame 的所有行,并在右侧 DataFrame 中缺失数据的位置填充 NaN。
    • 'right': 保留右侧 DataFrame 的所有行,并在左侧 DataFrame 中缺失数据的位置填充 NaN。
  • left_on 和 right_on: 分别指定左侧和右侧 DataFrame 中用于合并的列名。如果左右两侧的列名不同,可以使用这两个参数来指定。

  • left_index 和 right_index: 布尔值,指示是否使用左侧和右侧 DataFrame 的索引作为合并的键。默认为 False。

  • suffixes: 用于区分左右两个 DataFrame 中重叠列名的后缀字符串或元组。默认为 ('x', ' y')。

  • validate: 用于检查合并操作的合法性。可以设置为 'one_to_one'、'one_to_many'、'many_to_one' 或 'many_to_many'。默认为 None,表示不进行检查。

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)
print(df_merge)

输出结果:

image.png

数据合并(concat()方法)

pd.concat(objs,axis=0,join='outer',ignore_index=False,keys=None,levels=None,names=None,verify_integrity=False,copy=True)

参数说明:

  • objs: Series,DataFrame或Panel对象的序列或映射,如果传递了dict,则排序的键将用作键参数
  • axis: {0,1,...},默认为0,也就是纵向上进行合并。沿着连接的轴。
  • join: {'inner','outer'},默认为“outer”。如何处理其他轴上的索引。outer为联合和inner为交集。
  • ignore_index: boolean,default False。如果为True,请不要使用并置轴上的索引值。结果轴将被标记为0,...,n-1。如果要连接其中并置轴没有有意义的索引信息的对象,这将非常有用。注意,其他轴上的索引值在连接中仍然受到尊重。
  • keys: 序列,默认值无。使用传递的键作为最外层构建层次索引。如果为多索引,应该使用元组。
  • levels: 序列列表,默认值无。用于构建MultiIndex的特定级别(唯一值)。否则,它们将从键推断。
  • names:list,default无。结果层次索引中的级别的名称。
  • verify_integrity: boolean,default False。检查新连接的轴是否包含重复项。这相对于实际的数据串联可能是非常昂贵的。
  • copy: boolean,default True。如果为False,请勿不必要地复制数据。
  • sort : sort=False,列的顺序维持原样, 不进行重新排序。

纵向连接DataFrame对象

ignore_index=True,主要使用了这个元素

import pandas as pd

# 初始化两个DataFrame对象
df1 = pd.DataFrame([['a', 1], ['b', 2]],columns=['letter', 'number'])

df2 = pd.DataFrame([['c', 3], ['d', 4]],columns=['letter', 'number'])

print(df1)
print(df2)
# 合并对象
print(pd.concat([df1, df2]))
print(pd.concat([df1, df2],ignore_index=True))

image.png

注意:

df3 = pd.DataFrame({'letter':[('c', 3)],'number':[('d', 4)]})
print(df3)

注意的输出:

image.png

横向合并DataFrame对象

axis=1,主要使用了这个元素

import pandas as pd
# 初始化DataFrame对象
df1 = pd.DataFrame([['a', 1], ['b', 2]],
                   columns=['letter', 'number'])

df4 = pd.DataFrame([['bird', 'polly'], ['monkey', 'george']],
                   columns=['animal', 'name'])

print(df1)
print(df4)

# 合并对象
print(pd.concat([df1, df4], axis=1))

输出:

image.png

如果axis=0,输出则是:

image.png

两个DataFrame对象的列不完全相同

import pandas as pd

# 初始化DataFrame对象
df1 = pd.DataFrame([['a', 1], ['b', 2]],
                   columns=['letter', 'number'])

df3 = pd.DataFrame([['c', 3, 'cat'], ['d', 4, 'dog']],
                   columns=['letter', 'number', 'animal'])

print(df1)
print(df3)

# 合并对象
print(pd.concat([df1, df3], sort=False))  # sort=False : 列的顺序维持原样, 不进行重新排序。

# 合并相同的列
print(pd.concat([df1, df3], join='inner',ignore_index=True))  #ignore_index=True,就是将合并之后的行索引重新排序

image.png

数据导出

导出为.xlsx文件

导出数据为excel,主要使用到DataFrame对象的to_excel方法,语法如下:

DataFrame.to_excel(excel_writer, sheet_name='Sheet1', na_rep='', float_format=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=None)

参数说明:

  • ExcelWriter:将 DataFrame 输出到 Excel 的写入器对象。可以指定已存在的 ExcelWriter 对象,或者通过 filename 参数新建一个。
  • sheet_name:要将 DataFrame 写入的 Excel 工作表名称。默认为 'Sheet1'。
  • index:是否写入 DataFrame 的索引。默认为 False。
  • header:是否写入列名。默认为 True。
  • index_label:索引列的标签名。默认为 'Index'。
  • startrow、startcol:开始写入的行和列的索引(0 开始)。默认为 None,从第一行和第一列开始写入。
  • engine:用于写入 Excel 的引擎。默认为 'openpyxl'(对于 .xlsx 文件)和 'xlwt'(对于 .xls 文件)。
  • mode:写入模式,如 'a' 为追加模式,'w' 为覆盖模式。默认为 'w'。
  • encoding:文件编码。默认为 None,自动识别。
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)
df_merge.to_excel('merge.xlsx')
# 指定sheet_name
df1.to_excel('df1.xlsx',sheet_name='df1')  #导出df1,数据导出到sheet_name='df1'

导出为.csv文件

to_csv 是 pandas 库中 DataFrame 类的一个方法,用于将数据框(DataFrame)保存为 CSV 文件。 语法如下:

DataFrame.to_csv(path_or_buf=None, sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression='infer', quoting=None, quotechar='"', line_terminator=None, chunksize=None, date_format=None, doublequote=True, escapechar=None, decimal='.', errors='strict')

参数说明:

  • path_or_buf:要写入的文件路径或文件对象。
  • sep:用于分隔 CSV 文件中的列的字符。默认为 ','。
  • delimiter:与 sep 参数类似,用于指定分隔符。默认为 None。
  • header:是否写入列名。默认为 True,写入的意思。
  • index:是否写入 DataFrame 的索引。默认为 True保留的意思。
  • na_rep:用于替换缺失值的字符串。默认为 'NaN'。
  • float_format:用于格式化浮点数的字符串。默认为 None。
  • columns:要写入的数据框中的列。默认为 None,即写入所有列。
  • mode:写入模式,如 'w' 为覆盖模式,'a' 为追加模式。默认为 'w'。
  • encoding:文件编码。默认为 None,自动识别。
  • compression:用于指定压缩文件的参数。默认为 None。
import pandas as pd

data = [['a',110,105,99],['b',105,88,115],['c',109,120,130],['d',112,115]]
index = [1,2,3,4]
columns = ['name','语文','数学','英语']
df = pd.DataFrame(data=data, index=index, columns=columns)
print(df)

#相对位置,保存在程序所在路径下
df.to_csv('Result1.csv',encoding='gb2312')
#绝对位置
df.to_csv('d:\Result.csv',encoding='gb2312')
#分隔符,使用问号(?)分隔符分隔需要保存的数据
df.to_csv('Result2.csv',sep='?',encoding='gb2312')
#替换空值,缺失值保存为NA
df.to_csv('Result3.csv',na_rep='NA',encoding='gb2312')
#格式化数据,保留两位小数
df.to_csv('Result4.csv',float_format='%.2f',encoding='gb2312')
#保留某列数据,保存索引列和name列
df.to_csv('Result5.csv',columns=['name'],encoding='gb2312')
#是否保留列名,不保留列名
df.to_csv('Result6.csv',header=0,encoding='gb2312')
#是否保留行索引,不保留行索引
df.to_csv('Result7.csv',index=0,encoding='gb2312')

导出多个Sheet

导出多个Sheet,应首先使用pd.ExcelWriter()方法打开一个Excel文件,然后再使用to_excel()方法导出指定的Sheet。

import pandas as pd

data = [['a',110,105,99],['b',105,88,115],['c',109,120,130],['d',112,115]]
index = [1,2,3,4]
columns = ['A','语文','数学','英语']
df1 = pd.DataFrame(data=data, index=index, columns=columns)

df1.to_excel('df1.xlsx', sheet_name='df1')  #生成一个df1.xlsx文件,并且把数据放入sheet_name='df1'
work = pd.ExcelWriter('df2.xlsx')  # 新生成一个df2.xlsx文件
df1.to_excel(work, sheet_name='df2')
df1['A'].to_excel(work, sheet_name='df3')
work.close()

日期数据转换

DataFrame的日期数据转换

在日常工作中,常见的日期方式有很多种 例如’20221123’,‘2022.11.23’,‘2022/11/23’,‘23/11/2022’,‘23-Nov-22’,需要先将这些格式统一后才能进行后续的工作。 语法如下:

DataFrame.to_datetime(arg,errors=“ignore”,dayfirst=False,yearfirst=False,utc=None,box=True,format=None,exact=True,unit=None,inter_datetime=False,origin=“unix”,cache=False)

参数说明:

  • series:需要转换的Series。
  • format:日期时间格式字符串。
  • errors:如何处理格式字符串匹配失败的值,默认为'coerce',即将其转换为NaT。可选值有'ignore'(忽略错误)和'coerce'(将错误值转换为NaT)。
  • exact:布尔值,当为True时,所有的值都会被尝试转换,当为False时,只有符合format格式的值会被转换。默认值为True。
  • dayfirst:布尔值,当为True时,日期解析为月份/日/年的格式,当为False时,解析为日/月/年的格式。默认值为False。
  • yearfirst:布尔值,当为True时,解析年份在月份之前,当为False时,解析月份在年份之前。默认值为False。
  • convention:用于解析日期字符串的约定方式。可选值为'ECMAScript'、'ISO-8601'和'SQL'。默认值为'ECMAScript'。
  • infer_datetime_format:推断日期时间格式,如果格式无法推断,则使用尝试方法进行推断。默认为False。
  • projections:如果输入是一个Pandas DataFrame并且其中包含多个列用于日期/时间解析,则可以提供列名以进行投影。默认值为None。
import pandas as pd

df=pd.DataFrame({'原日期':['14-Feb-20', '02/14/2020', '2020.02.14', '2020/02/14','20200214']})
# print(df)
df['转换后的日期']=pd.to_datetime(df['原日期'])
print(df)

image.png

例如:

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]})
print(df)
df['组合后的日期']=pd.to_datetime(df)
print(df)

结果输出:

image.png

dt对象的使用

dt对象是Series对象中用于获取日期属性的一个访问器对象,通过他可以获取日期中的年月日星期季节等,还可以用于判断日期是否处在年底。

语法如下:

Series.dt()

常见参数说明:

  1. dt.year:返回序列中每个日期的年份。
  2. dt.quarter:返回序列中每个日期的季度(1-4)。
  3. dt.month:返回序列中每个日期的月份(1-12)。
  4. dt.day:返回序列中每个日期的日期(1-31)。
  5. dt.dayofweek:返回序列中每个日期的星期几(0-6,0代表星期一)
  6. dt.day_of_year:返回序列中每个日期的年份中的第几天(1-366)。
  7. dt.weekofyear:返回序列中每个日期在一年中的第几周(1-53)。
  8. dt.week:返回序列中每个日期的ISO 8601周数。
  9. dt.daysinmonth:返回序列中每个月的天数。
  10. dt.days_in_month:同 dt.daysinmonth。
  11. dt.tz:返回序列中每个日期的时区。
  12. dt.freq:返回序列的频率字符串。
  13. dt.to_period:将序列转换为Period类型。
  14. dt.to_series:将序列转换为Series类型,并保留原始索引。
  15. dt.to_datetime:将序列转换为datetime类型。
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['原日期'])
print(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)

image.png

获取日期区间的数据

获取日期区间的数据的方法是直接在DataFrame对象中输入日期获取日期区间,但前提是必须设置日期为索引。

import pandas as pd

df = pd.read_excel('mingribooks.xls')
df1=df[['订单付款时间','买家会员名','联系手机','买家实际支付金额']]
df1=df1.sort_values(by=['订单付款时间'])
df1 = df1.set_index('订单付款时间') # 将日期设置为索引
#获取某个区间数据
df2=df1['2018-05-11':'2018-06-10']
print(df2)

按不同时期统计并显示数据

按时期统计数据主要通过DataFrame对象的resample()方法结合数据计算函数实现。resample()方法主要应用于实践序列频率转换和重采样,它可以从日期中获取年月日星期季节等等,结合数据计算函数就可以实现年月日星期等不同日期统计数据。

import pandas as pd

aa =r'TB2018.xls'
df = pd.DataFrame(pd.read_excel(aa))
df1=df[['订单付款时间','买家会员名','联系手机','买家实际支付金额']]
df1 = df1.set_index('订单付款时间') # 将date设置为index

print('---------按月统计数据-----------')
#“MS”是每个月第一天为开始日期,“M”是每个月最后一天
print(df1.resample('M').sum().to_period('M'))


print('---------按季统计数据-----------')
#“QS”是每个季度第一天为开始日期,“Q”是每个季度最后一天
print(df1.resample('QS').sum())

print('---------按年统计数据-----------')
#“AS”是每年第一天为开始日期,“A”是每年最后一天
print(df1.resample('AS').sum())



print('---------按年统计并显示数据-----------')
#“AS”是每年第一天为开始日期,“A”是每年最后一天
print(df1.resample('AS').sum().to_period('A'))
print('---------按季度统计并显示数据-----------')
print(df1.resample('Q').sum().to_period('Q'))
print('---------按月统计并显示数据-----------')
print(df1.resample('M').sum().to_period('M'))
df2=df1.resample('M').sum().to_period('M')

print('---------按星期统计并显示数据-----------')
print(df1.resample('w').sum().to_period('W').head())

时间序列

注意: data_range()是pandas中常用的函数,用于生成一个固定频率的DatetimeIndex时间索引。原型:

date_range(start=None, end=None, periods=None, freq=None, tz=None, normalize=False, name=None, closed=None, **kwargs)

常用参数为start、end、periods、freq。

start:指定生成时间序列的开始时间

end:指定生成时间序列的结束时间

periods:指定生成时间序列的数量

freq:生成频率,默认‘D’,可以是’H’、‘D’、‘M’、‘5H’、‘10D’、…

函数调用时至少要指定参数start、end、periods中的两个。

pd.date_range('20200101',periods=10)  #指定开始时间和时间序列数量,注意,start、end都是闭区间

image.png

重采样(resample()方法)

在pandas中对时间序列的频率的调整称为重新采样,即将时间序列从一个频率转换到另一个频率的处理过程,例如,将每天一个频率转成5天一个频率。重采样主要使用resample()方法,该方法用于对常规时间序列重新采样和频率转换,包括降采样和升采样两种。语法如下:

resample(rule,how=None,axis=0,fill_method=None,closed=Nonelabel=None,convention=“start”,kind=None,loffset=None,limit=None,base=0,on=None,level=None)

常用参数说明:

  1. rule:表示重采样频率的字符串或DateOffset,比如M、5min等。
  2. how:用于产生聚合值的函数名或函数数组,默认为None。
  3. fill_method:表示升采样时如何插值,可以取值为fill、bfill或None,默认为None。
  4. closed:设置降采样哪一端是闭合的,可以取值为right或left。若设为right(默认),则表示划分为左开右闭的区间;若设为left,则表示划分为左闭右开的区间。
  5. label:表示降采样时设置聚合值的标签。
  6. convention:重采样日期时,低频转高频采用的约定,可以取值为start或end,默认为start。
  7. limit:表示前向或后向填充时,允许填充的最大时期数。
import pandas as pd
index = pd.date_range('02/02/2020', periods=9, freq='T')  #periods时间数量,freq='T'代表分钟
series = pd.Series(range(9), index=index)
print(series)
print(series.resample('3T').sum())

输出结果:

image.png

降采样处理

降采样是周期由高频率转向低频率。例如,将5分钟股票交易数据转换成日交易,按天统计的销售数据转换为按周统计。 数据降采样会涉及数据的聚合。例如,天数据变成周数据,那么就需要对1周对7天的数据进行聚合,聚合的方式主要包括求和求均值等。

import pandas as pd
df=pd.read_excel('time.xls')
df1=df.set_index('订单付款时间')
print(df1)

print(df1.resample('W').sum())
print(df1.resample('W',closed='left').sum())  #左闭右开

其他聚合方法:

print(df1.resample('w').min())  #最小值
print(df1.resample('w').max())  #最大值
print(df1.resample('w').mean())  #均值
print(df1.resample('w').mdeian())  #中值
print(df1.resample('w').first())  #返回第一个值
print(df1.resample('w').last())  #返回最后一个值

升采样处理

升采样是周期由低频率转向高频率。将数据从低频率转换到高频率时,就不需要聚合了,将其重采样到日频率,默认会引入缺失值。

例如,原来是按周统计到数据,现在变成按天统计。升采样会涉及数据到填充,根据填充的方法不同,填充的数据也不同。有以下几种方式。

1、不填充 空值用NaN值代替,使用asfreq()方法

2、向填充 用前面的值进行填充空值,使用ffill()或者pad()方法

3、向填充 用后面的值进行填充空值,使用bfill()方法

import pandas as pd
import numpy as np
rng=pd.date_range('20200202',periods=2)
s1=pd.Series(np.arange(1,3),index=rng)
print(rng)
print(s1)

s1_6h_asfreq=s1.resample('6H').asfreq()
print(s1_6h_asfreq)
s1_6h_ffill=s1.resample('6H').ffill()
print(s1_6h_ffill)
s1_6h_bfill=s1.resample('6H').bfill()
print(s1_6h_bfill)

时间序列数据汇总(ohic()函数)

在金融领域中,经常会看到开盘、收盘、最高价、最低价数据,而在pandas中经过重采样的数据也可以实现这样的结果,通过调用ohic()函数得到数据汇总结果,即开始值、结束值、最高值和最低值。

import pandas as pd
import numpy as np

rng=pd.date_range('20220202',periods=12,freq='T')
s1=pd.Series(np.arange(12),index=rng)
print(s1)
print(s1.resample('5min').ohlc())

输出结果:

image.png

移动窗口数据计算(rolling()函数)

通过重采样可以得到想要的任何频率的数据,但是这些数据也是一个时点的数据,那么就存在这样一个问题:时点的数据波动较大,某一点的数据就不能很好地表现它本身的特性,于是就有了 移动窗口的概念,简单地说,为了提升数据的可靠性,将某个点的取值扩大到包含这个点到一段区间,用区间来进行判断,这个区间就是窗口。

image.png

在pandas中可以通过rolling()函数实现移动窗口数据的计算。语法如下:

DataFrame.rolling(window, min_periods=None, center=False, win_type=None, on=None, axis=0, closed=None)

常用参数说明:

  • window:滚动窗口的大小。可以是一个整数,也可以是一个具有指定列名的列表。
  • min_periods:每个窗口最少需要有的观察值数量。如果窗口中的数据少于这个数量,该窗口的结果将会被替换为 NaN。默认为 None,即每个窗口都必须至少有一个观察值。
  • center:设置为 True,则会在窗口中间对齐数据。默认为 False。
  • win_type:提供窗口类型(例如 'gaussian', 'triang', 'blackman' 等)。默认为 None。
  • on:列名或列名的列表,用于计算滚动窗口。默认为 None,表示在所有列上应用滚动窗口。
  • axis:0 或 'index' 表示按行应用滚动窗口,1 或 'columns' 表示按列应用滚动窗口。默认为 0。
  • closed:用于定义左边界的参数。可以设置为 'left' 或 'right'。默认为 None,表示根据窗口类型自动选择。
import pandas as pd
index=pd.date_range('20200201','20200215')
print(index)
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)
print(s1_data.rolling(3).mean())

image.png