Skip to main content

CP010如何识别多天连续低温站点

阅读:-


在报表的应用中,有一类常见的应用是需要分析多天的数据,并从中提炼出多天连续满足特定条件的一些数据对象。这种应用特别适合针对股票,基金,气象站来进行分析,而这一类应用,假如我们用常规方法来处理是比较困难的,而 pandas 刚好提供了一种窗函数,可以很好的处理这一类问题,所以聪明的你就来看看吧。

10 pandas 应用-连续低温站点案例

10.1 用例背景

下面我们就举一个气象专业的例子, 假设在青年路地区,将这个地区划分了多个栅格,我们在每个栅格中放置一个气象站。当气象站的数据回传到中心机房以后,我们就可以基于一定的规则,判断采集到低温气象情况的站点,相关的数据样例为:

表 10-1 天粒度统计报表

dateworkstation-id
2019-12-15 0:00460-00-30000-100
2019-12-16 0:00460-00-30000-100
2019-12-17 0:00460-00-30000-100
2019-12-18 0:00460-00-30000-100
2019-12-19 0:00460-00-30000-100

备注: 如果一个站点在某一天采集的温度情况,属于高温,则不会出现在上表中。

那么经过一周以后,我们就可以收集到一个气象观测站多天的记录, 假设我们的规则是如果一个气象观测站连续 5 天都观测到了低温天气,那么这个站点所在的区域,就设定为低温站点。

合并的记录有

Start dateEnd dateworkstation-id持续天数
2019-12-15 0:002019-12-19 0:00460-00-30000-1005

那么合并以后,我们就很方便来观察这些低温站点的数据,这种

数据分析的方法我们称为窗口函数分析。

10.1.1 用例模型

下面将相关项目的用例进行说明。

1,用户输入期待处理的文件路径,输出结果文件的,相关的信息结构

[ 输入文件绝对路径,输出文件绝对路径]

举例如下:[D:\PAE\daily-WST.csv, D:\PAE\windows-WST.csv]

2、应用程序读取输入文件,转换为内存的一个 DF。

3,应用程序将 DF**按照时间顺序进行分片处理**

3.1 第一天出现的数据,将结果存入 DF1

3.2 第二天出现的数据,将结果存入 DF2

3.3 第三天出现的数据,将结果存入 DF3

3.4 第四天出现的数据,将结果存入 DF4

3.5 第五天出现的数据,将结果存入DF5

3.6 连续两天即为,DF5与DF4相同数据

3.7 连续三天即为,先用DF5与DF4进行比较得到相同数据newdata2, 在将newdata2与DF3进行比较得到连续三天相同的数据即为newdata3,以此类推得出连续四天连续五天的结果。

3.8:日期为第一天初始日期

4、应用程序将内存中的 newdata,也就是新生成的 DF, 写入输出结果 csv 文件的句柄, 相关文件决对路径来自输入数据。

举例:D:\PAE\windows-WST.csv

5,应用程序返回程序执行响应 [ 执行结果,输出结果文件信息]

其中执行结果:0 成功 1 失败

输出结果文件信息:提供输出结果文件的决对路径,举例如下:

举例:D:\PAE\ windows-WST..xlsx

10.2 IPO 分析

10.2.1 输入数据分析(I)

1、所需处理源文件,低温站点统计表,数据格式如下:

1587369454305

2、 输入参数为:

[D:\PAE\daily-WST.csv, D:\PAE\windows-WST.csv]

10.2.2 处理过程

核心的窗函数处理过程为:

3,应用程序将 DF 进行窗函数的分析过滤处理

3.1 设定所需提取的时间段为5天

3.2 分别按照时间提取第一天至第五天的数据存储至df1-df5

3.3 df1与df2均包含的数据为连续两天的值赋值为newdata2

3.4 将newdata2与df3进行比较均包含的数据赋值为newdata3即为连续三天出现的结果。

3.5 以此类推。

3.6日期为指定时间的起始日期

4 将连续不同天数的数据记录输出为,excle 的不同 Sheet 中,并署名为连续几天的数据。

10.2.3 输出数据

1587369491444

输出数据格式如下:

SequenceidStart dateEnd dateworkstation-id持续天数
02019-12-15 0:002019-12-19 0:00460-00-30000-1005

备注:此出的 sequence-id 是一个自增序列,从 0 开始,顺序递增。

备注:标准解题输出数据采用 csv 格式,筛选连续 5 天的站点就可以。

自己练习部分,可以使用 xlsx 格式,利用三个 sheet,输出连续 3 天,4 天,5 天的数据,参考以下的格式:

1587369566163

10.3 用例约束

1、 请使用 pandas

2、 请使用 python3 以上版本

10.4 扩展用例说明

1587369599993

图10-6 pandas内置窗函数解法

在前面的方案中,虽然解题过程比较方便,但是代码书写非常迂回,我们接下来研究一种内置函数的方法,而这种方法则需要应用一些高级特性。

10.4.1 用例模型(基于窗函数)

下面将相关项目的用例进行说明。

1,用户输入期待处理的文件路径,输出结果文件的,相关的信息结构

[ 输入文件绝对路径,输出文件绝对路径]

举例如下:[D:\PAE\daily-WST.csv, D:\PAE\windows-WST.csv]

2、应用程序读取输入文件,转换为内存的一个DF。

3,应用程序将DF进行窗函数的分析过滤处理

  1. 1 设定窗口宽度为5天,将过滤的结果存入DF1

3.2 将窗口的宽度设定为6天,将过滤的结果存入DF2

3.3 将窗口的宽度设定为7天,将过滤的结果存入DF3

3.4 将DF1,DF2,DF3 进行合并为一个新的DF

3.5 将DF进行去重处理。

3.6:生成开始日期,在pandas中的滑窗默认是右滑窗,也就是当前记录为窗口的最后一个记录,所以取到的是结束日期,

开始日期=结束日期-(窗口宽度-1)

备注:滑窗默认是右滑窗,也就是当前记录为窗口的最后一个记录,所以取到结束日期。 要分析连续出现问题,所以在滑窗范围内要有滑窗大小的记录数才能算是连续出现。要分析更多日期的连续需要设计更大的滑窗 。

4、应用程序将内存中的 data set,也就是新生成的 DF, 写入输出结果 csv 文件的句柄, 相关文件决对路径来自输入数据。

举例:D:\PAE\windows-WST.csv

5,应用程序返回程序执行响应 [ 执行结果,输出结果文件信息]

其中执行结果:0 成功 1 失败

输出结果文件信息:提供输出结果文件的决对路径,举例如下:

举例:D:\PAE\ windows-WST..xlsx

10.4.2 处理过程(基于窗函数)

核心的窗函数处理过程为:

3,应用程序将 DF 进行窗函数的分析过滤处理

  1. 1 设定窗口宽度为5天,将过滤的结果存入DF1

3.2 将窗口的宽度设定为6天,将过滤的结果存入DF2

3.3 将窗口的宽度设定为7天,将过滤的结果存入DF3

3.4 将DF1,DF2,DF3 进行合并为一个新的DF

3.5 将DF进行去重处理。

3.6:生成开始日期,在pandas中的滑窗默认是右滑窗,也就是当前记录为窗口的最后一个记录,所以取到的是结束日期,

开始日期=结束日期-(窗口宽度-1)

备注:滑窗默认是右滑窗,也就是当前记录为窗口的最后一个记录,所以取到结束日期。 要分析连续出现问题,所以在滑窗范围内要有滑窗大小的记录数才能算是连续出现。要分析更多日期的连续需要设计更大的滑窗 。

10.5 设计方案简介

10.5.1 普通方案

10.5.1.1 调用关系

1587369651378

1.5.1.2 流穿越

1、 data5

1587369667041

2、Result5

1587369680494

3、 写入本地

1587369699864

10.5.2 窗函数应用 1-连续五天模型

10.5.2.1 调用关系

1587369728148

10.5.2.2 流穿越

1、Df

1587369748222

3、 Res

注之前提到的,分组之后无法查看值,使用 list()函数即可,数据如下:

1587369773385

4、

df = df.loc[list(df.groupby('CGI').idxmax(axis=0)['统计'])]

1587369788669

10.5.3 窗函数应用 2-连续 5-7 天数据

10.5.3.1 调用关系

1587369817722

10.5.3.2 流穿越

1、 df

1587369838226

2、result

1587369853464

10.6 普通方案详解

10.6.1 领域模型分析

1587369891336

图 10-1 窗函数的普通方法

从上图可见,上图为常规方法,利用多个迭代处理,实现了最后的功能。

1.6.2 讨论点

以上的实现方案中,存在两个完善的点。

1.日期的硬编码问题。

1587369912105

在这个方案中,日期采用了硬编码的方式,这样方便扩展。

2、截止日期迭代,以及去重的问题

由于原数据有 7 天,所以至少需要设定三个 end date,建立一个

end_date_list[], 经过迭代以后,把相关的小区识别出来,但是这里有一个去重的问题。

1), 如果是连续 5 天的小区,可以直接去重就可以。

2),如果是连续 4 天的小区,也可直接去重。

3),如果连续 3 天小区,则要考虑是否呈现两条数据。

3.end_date_list[] , 最好能够自动扫描获得。

10.7 窗函数模型 2 方案详解(连续 5 天)

在前面的方案中,如果使用硬编码方案处理起来比较麻烦,所以我们考虑采用一种高级的窗函数编程方法。

10.7.1 窗函数简介

10.7.1.1 基本概念

1.为了处理数字数据,Pandas 提供了几个变体,如滚动,展开和指数移动窗口统计的权重。 其中包括总和,均值,中位数,方差,协方差,相关性等;

2.所谓窗口,就是将某个点的取值扩大到包含这个点的一段区间,用区间来进行判断;

3.移动窗口就是窗口向一端滑行,默认是从右往左,每次滑行并不是区间整块的滑行,而是一个单位一个单位的滑行;

4.窗口函数主要用于通过平滑曲线来以图形方式查找数据内的趋势。如果日常数据中有很多变化,并且有很多数据点可用,那么采样和绘图就是一种方法,应用窗口计算并在结果上绘制图形是另一种方法。 通过这些方法,可以平滑曲线或趋势。

10.7.1.2 Rolling()

1587369998811

  1. window:表示时间窗的大小,有两种形式:1)使用数值 int,则表示观测值的数量,即向前几个数据;2)也可以使用 offset 类型,这种类型较复杂,使用场景较少,此处暂不做介绍;

2.min_periods:每个窗口最少包含的观测值数量,小于这个值的窗口结果为 NA。值可以是 int,默认 None。offset 情况下,默认为 1;

3.center: 把窗口的标签设置为居中,布尔型,默认 False,居右

4.win_type: 窗口的类型。截取窗的各种函数。字符串类型,默认为 None;

5.on: 可选参数。对于 dataframe 而言,指定要计算滚动窗口的列。值为列名。 6.axis: 默认为 0,即对列进行计算 7.closed:定义区间的开闭,支持 int 类型的 window。对于 offset 类型默认是左开右闭的即默认为 right。可以根据情况指定为 left、both 等。

10.7.1.3 代码示例

示例中,由于窗口大小为 3(window),前两个元素有空值,第三个元素的值将是 n,n-1 和 n-2 元素的平均值。

1587370034302

1587370072669

10.7.1.4 常见用法

1.rolling()函数除了 mean(),还支持很多函数,

比如: count() 非空观测值数量 sum() 值的总和 median() 值的算术中值 min() 最小值 max() 最大 std() 贝塞尔修正样本标准差 var() 无偏方差 skew() 样品偏斜度(三阶矩) kurt() 样品峰度(四阶矩) quantile() 样本分位数(百分位上的值) cov() 无偏协方差(二元) corr() 相关(二进制)

  1. 借助 agg ()函数可以快速实现多个聚类函数,并输出结果,同时还可以进行重命名;

3) 代码示例

1587370101772

1587370120614

1587370137128

10.7.1.5 延伸用法

1.通过 rolling()函数与聚合函数的拼接,组成新的函数,可以更方便地实现窗口函数的功能;

2.这种用法,功能强大,代码简单,所有参数的设置基本一致;

3.列举如下 rolling_count() 计算各个窗口中非 NA 观测值的数量 rolling_sum() 计算各个移动窗口中的元素之和 rolling_mean() 计算各个移动窗口中元素的均值 rolling_median() 计算各个移动窗口中元素的中位数 rolling_var() 计算各个移动窗口中元素的方差 rolling_std() 计算各个移动窗口中元素的标准差 rolling_min() 计算各个移动窗口中元素的最小值 rolling_max() 计算各个移动窗口中元素的最大值 rolling_corr() 计算各个移动窗口中元素的相关系数 rolling_corr_pairwise() 计算各个移动窗口中配对数据的相关系数 rolling_cov() 计算各个移动窗口中元素的的协方差 rolling_quantile() 计算各个移动窗口中元素的分位数

10.7.1.6 自定义函数

1.除了支持聚合函数,通过 rolling().apply()方法,还可以在移动窗口上使用自己定义的函数,实现某些特殊功能;

2.唯一需要满足的是,在数组的每一个片段上,函数必须产生单个值;

3.代码示例

1587370173525

以上资料,参考链接 https://www.jianshu.com/p/b8c795345e93

10.7.2 窗函数语法详解

1587370196196

10.7.2.1 窗函数论证

10.7.2.1 新建数组:

import pandas as pd
 index=pd.date_range('20190116','20190130')
 data=[4,8,6,5,9,1,4,5,2,4,6,7,9,13,6]
 ser_data=pd.Series(data,index=index)
 print(ser_data)

1587370270760

10.7.2.2 使用窗函数

new_data=ser_data.rolling(3).mean()

1587370299023

10.7.2.3 效果对比:

1587370378405

10.7.3 主要流转换过程

10.7.3.1 通常方案读取文件

假设我们按照一般化的方法读取文件,那么相关的日期字段会按照字符串形式来呈现。

df = pd.read_csv('./daily-WST.csv', encoding='gbk')

1587370414104

10.7.3.2 日期化读取文件

选择日期化的读写方案,就可以很方便的将需要处理的时间对象修改为日期类型。

df = pd.read_csv('./daily-WST.csv', encoding='gbk', parse_dates=['日期'], index_col=['日期'])

1587370465094

10.7.3.3 df[‘统计’] = 1

新增加一个字段,命名为‘统计’,用于标记相关的小区出现的次数。

1587370486935

10.7.3.4 f = df.groupby(‘CGI’)

由于考虑到是按照同一个小区连续出现的次数来分组,所以我们考虑使用字段’CGI’进行分组。

f = df.groupby('CGI')
 print(f)
 print([i  for i in df.groupby('CGI') ])
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000005361CF3108>

因为分组以后,是一个不可读对象,所以我们用迭代的方式打印相关的内容

1587370532995

从上图可见,经过分组以后,成为多个组,每组之中的数据的 cgi 都是相同的。

如果单步打印,相关的结果说明如下:

1587370569276

10.7.3.5 df.groupby(‘CGI’).rolling(‘5d’)

输出

RollingGroupby [window=432000000000000,min_periods=1,center=False,win_type=freq,axis=0]

1587370589179

这个结果是无法直接打印的。

1587370603620

所以,只能添加 sum 的方式查看。

1587370617925

这个是累加求和的形式。

10.7.3.6 df.groupby(‘CGI’).rolling(‘5d’).sum()

1587370639279

10.7.3.7 求分组项的最大值

9、res=df.groupby(‘CGI’).idxmax(axis=0)[‘统计’]

分组后是,一个 cgi 对应多个,统计值嘛,这个就是选取统计值最大的保存下来。

他返回的是,CGI,以及最大值的时间,开始不是有五个时间段嘛,现在每个 cgi 都是一个时间了。

[('400-01-1010863104-132', Timestamp('2019-12-15 00:00:00')), ('400-01-1010903040-129', Timestamp('2019-12-17 00:00:00')), ('400-01-1010903040-132', Timestamp('2019-12-11 00:00:00')), ('400-01-1010903040-148', Timestamp('2019-12-15 00:00:00')), ('400-01-1010903040-158', Timestamp('2019-12-15 00:00:00')), ('400-01-1010903040-159', Timestamp('2019-12-17 00:00:00')), ('400-01-1010903040-160', Timestamp('2019-12-11 00:00:00')), ('400-01-1010903040-161', Timestamp('2019-12-13 00:00:00'))]

1587370691802

从上图可见,这是一个序列对象。如果要打印,则需要列表化以后,在打印输出。

10.7.3.8 获得最后的输出值

10、df = df.loc[list(df.groupby(‘CGI’).idxmax(axis=0)[‘统计’])]

这一步就用.loc 这个函数,查找值,返回具体的每行中全部的数据。

1587370714240

10.7.3.9 输出数据

1587370733898

10.7.4 领域对象模型

10.7.4.1 领域对象模型概述

1587370760884

图 10-2 连续5天的窗函数模型

从上图可见,以上是相关的处理模型,核心的处理有两个

1,经过分组和窗函数计算以后,获得了一个 DF,其中有 1 个 cgi 的多天记录的详细信息。

2、利用 idxmaX 函数,求出了连续的最大天数,相关的数据返回为一个 series 对象。

10.7.4.2 Index object

1587370786098

在本案例中,aaa 本质是一个 index 对象。

aaa=df.groupby(‘CGI’).idxmax(axis=0)[‘统计’]

1587370802175

1587370816147

1587370829602

这里 index 是 pandas 的一个专属的优化对象。

1587370843881

支持的主要方法有:

1587370859348

10.7.5 关键知识点

窗函数模型1,分组求最大值idxmax(axis=0)[‘统计’]
2,DF 更新数据df.loc
3,series 的结构归纳 series 的信息结构和方法
4,df 基于日期读取文件parse_dates index_col
5,窗函数的应用rolling

10.7.6 分组求最大值

见 8.4.4,分组聚合,其 idxmax 为最大值,用法与 add、最小值,平均数等一样

10.7.7 DF 更新数据

见 9.6.4.4

10.7.7.1 Case 举例如下:

源数据:

1587370996040

index_col 默认值(index_col = None)——重新设置一列成为 index 值

import pandas as pd

import os

os.chdir('C:/Users/Administrator/Desktop')

df = pd.read_excel('数据.xls')

输出:

1587371010654

index_col=False——重新设置一列成为 index 值

import pandas as pd

import os

os.chdir('C:/Users/Administrator/Desktop')

df = pd.read_excel('数据.xls', index_col=False)

输出:

1587371025073

index_col=0——第一列为 index 值

import pandas as pd

import os

os.chdir('C:/Users/Administrator/Desktop')

df = pd.read_excel('数据.xls', index_col=0)

输出:

10.7.8 series 的结构

见 9.6.4.4

10.7.9 df 基于日期读取文件

10.7.9.1 应用目的

格式化日期

10.7.9.2 语法说明

df = pd.read_csv('', encoding='gbk', parse_dates=['日期'], index_col=['日期'])
**parse_dates参数**:将csv中的时间字符串转换成日期格式
**index_col 默认值**(index_col = None)——重新设置一列成为index值

10.7.9.3 case 举例

1587371137366

1、通常方案读取文件
df = pd.read_csv('./daily-WST.csv', encoding='gbk')

1587371167791

2、日期化读取文件
df = pd.read_csv('./daily-WST.csv', encoding='gbk', parse_dates=['日期'], index_col=['日期'])

1587371189283

10.7.9.4 注意事项

归一化,data 中的日期,方便后续的 information 提取

10.7.10 窗函数的应用

10.7.10.1 应用目的

在建模过程中,我们常常需要需要对有时间关系的数据进行整理。比如我们想要得到某一时刻过去 30 分钟的销量(产量,速度,消耗量等),传统方法复杂消耗资源较多,pandas 提供的 rolling 使用简单,速度较快。

10.7.10.2 语法说明

函数原型和参数说明

pandas 中提供了 pandas.DataFrame.rolling 这个函数来实现滑动窗口值计算,下面是这个函数的原型:

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

1587371271232

window:表示时间窗的大小,注意有两种形式(int or offset)。如果使用 int,则数值表示计算统计量的观测值的数量即向前几个数据。如果是 offset 类型,表示时间窗的大小。pandas offset 相关可以参考这里。

min_periods:最少需要有值的观测点的数量,对于 int 类型,默认与 window 相等。对于 offset 类型,默认为 1。

freq:从 0.18 版本中已经被舍弃。

center:是否使用 window 的中间值作为 label,默认为 false。只能在 window 是 int 时使用。

10.7.10.3 case 举例

1587371301866

1 新建数组:
import pandas as pd
 index=pd.date_range('20190116','20190130')
 data=[4,8,6,5,9,1,4,5,2,4,6,7,9,13,6]
 ser_data=pd.Series(data,index=index)
 print(ser_data)

1587371334411

2 使用窗函数
new_data=ser_data.rolling(3).mean()

1587371362066

3 效果对比:

1587371375161

10.7.10.4 注意事项

1.需要归一化 data 格式

2.一般应用场景与分组混合使用

3.输出信息需要考虑去重、格式化等问题

10.7.11 Pandas-Isin 的使用

10.7.11.1 应用目的

使用这个函数就是用来清洗数据,删选过滤掉 DataFrame 中一些行。

10.7.11.2 语法说明

Df.isin()

10.7.11.3 case 举例

1587371438796

1587371453848

1587371479951

10.7.11.4 注意事项

isin()的逆函数

没有 isnotin,它的反函数就是在前面加上 ~ ,其他用法同上。

10.8

以上就是窗函数的应用,一个简约,但是不简单的应用函数。一旦掌握了这个函数,你就可以很方便的处理金融类的大数据了。

分享到微博
Starter
MicroServ
Tutorials
Report
Blog