Pandas实战案例 | 冷空气活动寒潮级别分类

2024-01-15 20:40

本文主要是介绍Pandas实战案例 | 冷空气活动寒潮级别分类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理。

PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取

python免费学习资料以及群交流解答点击即可加入


大家好,今天介绍如何把基础函数groupby和diff方法通过复杂而清晰逻辑去解决令人头大的需求,优雅~
目录:

  • 需求分析
  • 读取数据
  • 拿一个分组进行测试
  • 获取满足寒潮定义条件的对应数据id
  • 分组编号生成器
  • 测试对所有站计算寒潮
  • 测试所有寒潮级别
  • 完整代码

需求分析

寒潮的定义:

 

数据的输入和输出格式:

 

统计口径确认:

 

我一开始不理解,24小时内降温幅度大于8度如何计算,与需求方确认后,可以通过2日温度之差来计算。同样48小时内降温幅度可以用3日温度之差来代表,72小时内降温幅度可以用4日温度之差来代表,需求方的解释:

 

好了,理解清楚了需求,咱们就可以开始干活了:

读取数据

首先读取数据:

import pandas as pd
import numpy as npdf = pd.read_csv("data.csv")
df

结果:

 

拿一个分组进行测试

取出某个分组,用于测试:

tmp = df.groupby('number').get_group('e332')
tmp

结果:

 

获取满足寒潮定义条件的对应数据id

 

上图的极端情况显示,三大满足条件的id可能出现重复的情况,所以我使用了set这个无序不重复集合来保存id:

cold_wave_idxs = set()
# 获取2天内降温幅度超过8对应的数据id
ids = tmp.index[tmp.temperature.diff(-1) >= 8].values
cold_wave_idxs.update(ids)
cold_wave_idxs.update(ids+1)
# 获取3天内降温幅度超过10对应的数据id
ids = tmp.index[tmp.temperature.diff(-2) >= 10].values
cold_wave_idxs.update(ids)
cold_wave_idxs.update(ids+1)
cold_wave_idxs.update(ids+2)
# 获取4天内降温幅度超过12对应的数据id
ids = tmp.index[tmp.temperature.diff(-3) >= 12].values
cold_wave_idxs.update(ids)
cold_wave_idxs.update(ids+1)
cold_wave_idxs.update(ids+2)
cold_wave_idxs.update(ids+3)
# 排序并转换成列表
cold_wave_idxs = sorted(cold_wave_idxs)
print(cold_wave_idxs)

结果:

[11928, 11929, 11930, 11931, 11939, 11940, 11949, 11950, 11951, 11952, 11955, 11956, 11957, 11958, 12007, 12008, 12154, 12155, 12192, 12193, 12201, 12202, 12203, 12223, 12224, 12225, 12228, 12229, 12230]
上述代码中cold_wave_idxs.update(ids+1)表示,把ids列表里每个id的后一个id也添加到最终列表里,利用了numpy数组广播变量的特性,+2和+3也是同理。

上述结果就是从站码为'e332'的分组中计算出满足寒潮定义的对应数据id。

从结果可以看出,凡是连续的id都可以看作一个寒潮的过程,所以现在我们需要将每个寒潮过程都分为一组,为了作这样的分组,我发明了一种分组编号生成器的写法,下面已经封装成了一个方法:

分组编号生成器

def generate_group_num(values, diff=1):group_ids = []group_id = 0last_v = 0for value in values:if value-last_v > diff:group_id += 1group_ids.append(group_id)last_v = valuereturn group_ids

上面的方法实现了一个分组编号生成器,对于一段序列凡是连续的数字都会给一个相同的分组编号。

测试一下分组效果:

for i, cold_wave_idx_serial in pd.Series(cold_wave_idxs).groupby(generate_group_num(cold_wave_idxs)):cold_wave_idx_serial = cold_wave_idx_serial.valuesprint(cold_wave_idx_serial)

结果:

[11928 11929 11930 11931]
[11939 11940]
[11949 11950 11951 11952]
[11955 11956 11957 11958]
[12007 12008]
[12154 12155]
[12192 12193]
[12201 12202 12203]
[12223 12224 12225]
[12228 12229 12230]

从结果可以看到,凡是连续的序列都分到了一组,不是连续的序列就没有分到一组。

测试对所有站计算寒潮

首先将前面的测试好的用于获取满足寒潮定义的id的过程封装成方法:

def get_cold_wave_idxs(df, cold_wave_level=(8, 10, 12)):cold_wave_idxs = set()ids = df.index[df.temperature.diff(-1) >= cold_wave_level[0]].valuescold_wave_idxs.update(ids)cold_wave_idxs.update(ids+1)ids = df.index[df.temperature.diff(-2) >= cold_wave_level[1]].valuescold_wave_idxs.update(ids)cold_wave_idxs.update(ids+1)cold_wave_idxs.update(ids+2)ids = df.index[df.temperature.diff(-3) >= cold_wave_level[2]].valuescold_wave_idxs.update(ids)cold_wave_idxs.update(ids+1)cold_wave_idxs.update(ids+2)cold_wave_idxs.update(ids+3)return sorted(cold_wave_idxs)

然后运行:

cold_wave_result = []for number, tmp in df.groupby('number'):cold_wave_idxs = get_cold_wave_idxs(tmp, (8, 10, 12))for i, cold_wave_idx_serial in pd.Series(cold_wave_idxs).groupby(generate_group_num(cold_wave_idxs)):cold_wave_idx_serial = cold_wave_idx_serial.valuesstart_id, end_id = cold_wave_idx_serial[0], cold_wave_idx_serial[-1]#  假如最低温度小于4度,则说明满足全部条件if tmp.loc[end_id, 'temperature'] <= 4:cold_wave_result.append((number, tmp.loc[start_id, 'date'], tmp.loc[end_id, 'date'],tmp.loc[start_id, 'temperature'], tmp.loc[end_id, 'temperature'],end_id-start_id+1,tmp.loc[start_id, 'temperature'] -tmp.loc[end_id, 'temperature'],'寒潮'))
cold_wave_result = pd.DataFrame(cold_wave_result, columns=['站号', '开始日期', '结束日期', '开始温度', '结束温度',  '寒潮天数', '温度差', '寒潮类型'])
cold_wave_result

结果:


感觉没啥问题。

 

所有寒潮级别都测试一下:

测试所有寒潮级别

cold_wave_all = [{'cold_wave_temperature_diffs': (8, 10, 12),'min_temperature_limit': 4,'cold_wave_type': '寒潮'},{'cold_wave_temperature_diffs': (10, 12, 14),'min_temperature_limit': 2,'cold_wave_type': '强寒潮'},{'cold_wave_temperature_diffs': (12, 14, 16),'min_temperature_limit': 0,'cold_wave_type': '超强寒潮'}
]
cold_wave_result = []for number, tmp in df.groupby('number'):for cold_wave_dict in cold_wave_all:cold_wave_idxs = get_cold_wave_idxs(tmp, cold_wave_dict['cold_wave_temperature_diffs'])if len(cold_wave_idxs) < 2:continuefor i, cold_wave_idx_serial in pd.Series(cold_wave_idxs).groupby(generate_group_num(cold_wave_idxs)):cold_wave_idx_serial = cold_wave_idx_serial.valuesstart_id, end_id = cold_wave_idx_serial[0], cold_wave_idx_serial[-1]#  假如最低温度小于指定度数,则说明满足全部条件if tmp.loc[end_id, 'temperature'] <= cold_wave_dict['min_temperature_limit']:cold_wave_result.append((number, tmp.loc[start_id, 'date'], tmp.loc[end_id, 'date'],tmp.loc[start_id, 'temperature'], tmp.loc[end_id, 'temperature'],end_id-start_id+1,tmp.loc[start_id, 'temperature'] - tmp.loc[end_id, 'temperature'],cold_wave_dict['cold_wave_type']))
cold_wave_result = pd.DataFrame(cold_wave_result, columns=['站号', '开始日期', '结束日期', '开始温度', '结束温度',  '寒潮天数', '温度差', '寒潮类型'])
cold_wave_result

结果:


暂时也未发现错误。那么整理一下最终代码吧:

 

完整代码

import pandas as pd
import numpy as npdef generate_group_num(values, diff=1):group_ids = []group_id = 0last_v = 0for value in values:if value-last_v > diff:group_id += 1group_ids.append(group_id)last_v = valuereturn group_idsdef get_cold_wave_idxs(df, cold_wave_level=(8, 10, 12)):cold_wave_idxs = set()ids = df.index[df.temperature.diff(-1) >= cold_wave_level[0]].valuescold_wave_idxs.update(ids)cold_wave_idxs.update(ids+1)ids = df.index[df.temperature.diff(-2) >= cold_wave_level[1]].valuescold_wave_idxs.update(ids)cold_wave_idxs.update(ids+1)cold_wave_idxs.update(ids+2)ids = df.index[df.temperature.diff(-3) >= cold_wave_level[2]].valuescold_wave_idxs.update(ids)cold_wave_idxs.update(ids+1)cold_wave_idxs.update(ids+2)cold_wave_idxs.update(ids+3)return sorted(cold_wave_idxs)df = pd.read_csv("data.csv")
cold_wave_all = [{'cold_wave_temperature_diffs': (8, 10, 12),'min_temperature_limit': 4,'cold_wave_type': '寒潮'},{'cold_wave_temperature_diffs': (10, 12, 14),'min_temperature_limit': 2,'cold_wave_type': '强寒潮'},{'cold_wave_temperature_diffs': (12, 14, 16),'min_temperature_limit': 0,'cold_wave_type': '超强寒潮'}
]
cold_wave_result = []for number, tmp in df.groupby('number'):for cold_wave_dict in cold_wave_all:cold_wave_idxs = get_cold_wave_idxs(tmp, cold_wave_dict['cold_wave_temperature_diffs'])if len(cold_wave_idxs) < 2:continuefor i, cold_wave_idx_serial in pd.Series(cold_wave_idxs).groupby(generate_group_num(cold_wave_idxs)):cold_wave_idx_serial = cold_wave_idx_serial.valuesstart_id, end_id = cold_wave_idx_serial[0], cold_wave_idx_serial[-1]#  假如最低温度小于指定度数,则说明满足全部条件if tmp.loc[end_id, 'temperature'] <= cold_wave_dict['min_temperature_limit']:cold_wave_result.append((number, tmp.loc[start_id, 'date'], tmp.loc[end_id, 'date'],tmp.loc[start_id, 'temperature'], tmp.loc[end_id, 'temperature'],end_id-start_id+1,tmp.loc[start_id, 'temperature'] - tmp.loc[end_id, 'temperature'],cold_wave_dict['cold_wave_type']))
cold_wave_result = pd.DataFrame(cold_wave_result, columns=['站号', '开始日期', '结束日期', '开始温度', '结束温度',  '寒潮天数', '温度差', '寒潮类型'])
cold_wave_result.to_excel("cold_wave.xlsx", index=False)

最终得到的结果:

这篇关于Pandas实战案例 | 冷空气活动寒潮级别分类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/610151

相关文章

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

Java MQTT实战应用

《JavaMQTT实战应用》本文详解MQTT协议,涵盖其发布/订阅机制、低功耗高效特性、三种服务质量等级(QoS0/1/2),以及客户端、代理、主题的核心概念,最后提供Linux部署教程、Sprin... 目录一、MQTT协议二、MQTT优点三、三种服务质量等级四、客户端、代理、主题1. 客户端(Clien

在Spring Boot中集成RabbitMQ的实战记录

《在SpringBoot中集成RabbitMQ的实战记录》本文介绍SpringBoot集成RabbitMQ的步骤,涵盖配置连接、消息发送与接收,并对比两种定义Exchange与队列的方式:手动声明(... 目录前言准备工作1. 安装 RabbitMQ2. 消息发送者(Producer)配置1. 创建 Spr

深度解析Spring Boot拦截器Interceptor与过滤器Filter的区别与实战指南

《深度解析SpringBoot拦截器Interceptor与过滤器Filter的区别与实战指南》本文深度解析SpringBoot中拦截器与过滤器的区别,涵盖执行顺序、依赖关系、异常处理等核心差异,并... 目录Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编

MySQL中的索引结构和分类实战案例详解

《MySQL中的索引结构和分类实战案例详解》本文详解MySQL索引结构与分类,涵盖B树、B+树、哈希及全文索引,分析其原理与优劣势,并结合实战案例探讨创建、管理及优化技巧,助力提升查询性能,感兴趣的朋... 目录一、索引概述1.1 索引的定义与作用1.2 索引的基本原理二、索引结构详解2.1 B树索引2.2

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

Java Web实现类似Excel表格锁定功能实战教程

《JavaWeb实现类似Excel表格锁定功能实战教程》本文将详细介绍通过创建特定div元素并利用CSS布局和JavaScript事件监听来实现类似Excel的锁定行和列效果的方法,感兴趣的朋友跟随... 目录1. 模拟Excel表格锁定功能2. 创建3个div元素实现表格锁定2.1 div元素布局设计2.