数据科学的秘密武器:defaultdict——Python字典的自动化填充神器,让数据结构更灵活

 

目录

什么是defaultdict

引入动机

创建与初始化

工作原理

自定义默认值函数

注意事项

使用案例

使用场景 1: 计数

使用场景 2: 分组数据

使用场景 3: 嵌套字典结构

进阶案例使用

进阶案例 1: 使用 defaultdict 实现词频统计并排序

进阶案例 2: 使用 defaultdict 实现多层嵌套的字典结构


什么是defaultdict

defaultdict 是 Python 标准库 collections 模块中的一个非常有用的类,它提供了一个带有默认值的字典(dictionary)。与普通字典相比,defaultdict 的特别之处在于它允许你指定一个函数,该函数会在字典中访问的键不存在时自动被调用,从而提供一个默认值。这个特性使得在处理数据时,特别是在处理可能缺少某些键的数据时,代码更加简洁和高效。

引入动机

普通字典(dict)在访问不存在的键时会引发 KeyError。为了处理这种情况,通常需要编写额外的代码来检查键是否存在,或者在使用键之前先给字典设置一个默认值。而 defaultdict 通过提供一个默认的值或值的生成函数,自动处理了这种情况,使得代码更加简洁和易于编写。

创建与初始化

defaultdict 通过其构造函数接受一个函数作为参数来创建。这个函数不接受任何参数,并返回一个值,该值将用作字典中不存在的键的默认值。常见的用法包括使用内置的工厂函数(如 intlistset)来创建不同类型的默认值。

from collections import defaultdict  # 使用 list 作为默认值  
dd_list = defaultdict(list)  # 使用 int 作为默认值  
dd_int = defaultdict(int)  # 使用 set 作为默认值  
dd_set = defaultdict(set)

工作原理

当尝试访问 defaultdict 中不存在的键时,defaultdict 会自动调用其构造函数中指定的函数来生成一个默认值,并将该值与键一起存储在字典中。这意味着,每次访问不存在的键时,都会得到一个新的默认值实例(对于像 list 或 set 这样的可变类型),而对于像 int 这样的不可变类型,则始终返回同一个默认值(但可以通过赋值操作来修改它)。

dd_list['a'].append(1)  # 'a' 不存在,调用 list() 创建一个列表并附加 1  
print(dd_list)  # 输出: defaultdict(<class 'list'>, {'a': [1]})  dd_int['x'] += 1  # 'x' 不存在,调用 int() 创建一个整数 0,然后加 1  
print(dd_int)  # 输出: defaultdict(<class 'int'>, {'x': 1})

自定义默认值函数

除了使用内置的工厂函数外,还可以传递自定义函数作为 defaultdict 的默认值生成器。这允许创建更复杂的默认值结构。

def my_default():  return {'count': 0, 'data': []}  dd_custom = defaultdict(my_default)  
dd_custom['key1']['count'] += 1  
dd_custom['key1']['data'].append('item')  
print(dd_custom)  # 输出包含自定义结构的 defaultdict

注意事项

  • 默认值函数不应接受任何参数,并返回一个值作为默认值。
  • 对于像 listset 等可变类型,每次访问不存在的键时都会创建一个新的实例。因此,如果需要在多个键之间共享状态,请小心使用。
  • defaultdict 提供了与普通字典相同的接口,包括 update()keys()values()items() 等方法。

使用案例

使用场景 1: 计数

当需要对一组元素进行计数时,defaultdict 可以非常方便地避免检查键是否存在的麻烦。

案例代码:

from collections import defaultdict  # 创建一个defaultdict,其默认值为int类型的0  
counts = defaultdict(int)  # 假设我们有一个单词列表  
words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']  # 对每个单词进行计数  
for word in words:  counts[word] += 1  # 如果word不在字典中,则默认值为0,然后加1  # 打印结果  
for word, count in counts.items():  print(f"{word}: {count}")  # 运行结果  
# apple: 3  
# banana: 2  
# cherry: 1  # 代码描述: 使用defaultdict对单词列表中的每个单词进行计数,无需显式检查键是否存在。

使用场景 2: 分组数据

当你需要将数据分组到不同的子结构中时(如列表或集合),defaultdict 可以帮助你快速初始化这些子结构。

案例代码:

from collections import defaultdict  # 创建一个defaultdict,其默认值为空列表  
groups = defaultdict(list)  # 假设我们有一组学生及其所属班级  
students = [('Alice', 'A'), ('Bob', 'B'), ('Charlie', 'A'), ('David', 'C'), ('Eve', 'B')]  # 根据班级将学生分组  
for student, class_ in students:  groups[class_].append(student)  # 打印结果  
for class_, students_in_class in groups.items():  print(f"Class {class_}: {students_in_class}")  # 运行结果  
# Class A: ['Alice', 'Charlie']  
# Class B: ['Bob', 'Eve']  
# Class C: ['David']  # 代码描述: 使用defaultdict将学生按班级分组到不同的列表中。

使用场景 3: 嵌套字典结构

当你需要处理嵌套的字典结构,并且想要自动初始化缺失的嵌套级别时,defaultdict 可以非常有用。

案例代码:

from collections import defaultdict  # 创建一个defaultdict,其默认值为另一个defaultdict,后者的默认值为int类型的0  
nested_dict = defaultdict(lambda: defaultdict(int))  # 假设我们要记录一些人的年龄和他们的身高(单位:厘米)  
data = [  ('Alice', 'age', 30),  ('Alice', 'height', 165),  ('Bob', 'age', 25),  ('Bob', 'height', 175),  ('Charlie', 'age', 35),  
]  # 填充嵌套字典  
for name, attribute, value in data:  nested_dict[name][attribute] = value  # 打印结果  
for name, attributes in nested_dict.items():  print(f"{name}: {attributes}")  # 运行结果  
# Alice: defaultdict(<class 'int'>, {'age': 30, 'height': 165})  
# Bob: defaultdict(<class 'int'>, {'age': 25, 'height': 175})  
# Charlie: defaultdict(<class 'int'>, {'age': 35})  # 注意:实际输出中defaultdict的显示可能略有不同,但核心结构是正确的。  # 代码描述: 使用嵌套的defaultdict来记录人的不同属性(如年龄和身高),自动初始化缺失的嵌套级别。

进阶案例使用

进阶案例 1: 使用 defaultdict 实现词频统计并排序

案例代码:

from collections import defaultdict  # 假设我们有一段文本  
text = "this is a sample text to demonstrate the use of defaultdict for word frequency analysis"  # 使用空格分割文本成单词列表,并转换为小写以忽略大小写差异  
words = text.lower().split()  # 创建一个defaultdict来统计词频,默认值为int类型的0  
word_counts = defaultdict(int)  # 统计每个单词的出现次数  
for word in words:  # 过滤掉标点符号等非单词字符(这里简化处理,只移除单引号)  word = word.replace("'", "")  # 忽略空字符串  if word:  word_counts[word] += 1  # 将词频统计结果转换为列表,以便排序  
sorted_word_counts = sorted(word_counts.items(), key=lambda x: x[1], reverse=True)  # 打印结果  
for word, count in sorted_word_counts:  print(f"{word}: {count}")  # 运行结果(注意:由于文本较短且随机,结果可能与示例不同)  
# to: 2  
# of: 1  
# use: 1  
# text: 1  
# this: 1  
# the: 1  
# sample: 1  
# a: 1  
# demonstrate: 1  
# is: 1  
# defaultdict: 1  
# for: 1  
# word: 1  
# analysis: 1  
# frequency: 1  # 代码描述: 使用defaultdict对一段文本进行词频统计,并根据词频进行降序排序。

进阶案例 2: 使用 defaultdict 实现多层嵌套的字典结构

案例代码:

from collections import defaultdict  # 创建一个defaultdict,其默认值为另一个defaultdict,后者再默认为另一个defaultdict,以支持多层嵌套  
nested_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))  # 假设我们要记录不同年份、不同月份、不同日期的天气情况(晴、阴、雨)  
data = [  ('2023', '01', '01', '晴'),  ('2023', '01', '02', '阴'),  ('2023', '01', '03', '雨'),  ('2023', '02', '01', '晴'),  ('2022', '12', '31', '晴'),  
]  # 填充多层嵌套字典  
for year, month, day, weather in data:  nested_dict[year][month][day][weather] += 1  # 打印结果(部分)  
for year, months in nested_dict.items():  print(f"Year: {year}")  for month, days in months.items():  print(f"  Month: {month}")  for day, weather_counts in days.items():  print(f"    Day: {day}, {weather_counts}")  # 注意:由于实际输出会非常长且包含嵌套结构,这里只展示了部分输出结构  # 运行结果(简化)  
# Year: 2023  
#   Month: 01  
#     Day: 01, defaultdict(<class 'int'>, {'晴': 1})  
#     Day: 02, defaultdict(<class 'int'>, {'阴': 1})  
#     Day: 03, defaultdict(<class 'int'>, {'雨': 1})  
#   Month: 02  
#     Day: 01, defaultdict(<class 'int'>, {'晴': 1})  
# Year: 2022  
#   Month: 12  
#     Day: 31, defaultdict(<class 'int'>, {'晴': 1})  # 注意:为了简化输出,这里省略了嵌套的 defaultdict 显示,实际输出中会显示 defaultdict。  # 代码描述: 使用多层嵌套的 defaultdict 来记录不同年份、月份、日期的天气情况,并统计每种天气的出现次数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1544248.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

OpenCSG推出StarShip SecScan:AI驱动的软件安全革新

OpenCSG 导读 如今&#xff0c;IT 技术迅速发展&#xff0c;软件安全不仅是企业稳健运营的基础&#xff0c;更是整个社会经济体系安全的保障。加强软件安全&#xff0c;尤其是在开发阶段识别和修补漏洞&#xff0c;是企业必须重视的问题。国际数据公司&#xff08;IDC&#xf…

MyBatis 入门教程-搭建入门工程

Maven作为一个优秀的项目构建和管理工具,在日常的开发中被大多数开发者使用,后续的项目也是基于Maven来构建。 创建一个Maven项目 利用IDEA创建项目工具来创建一个Maven项目 添加MyBatis的依赖 这里可以从Maven仓库地址中进行查看, https://mvnrepository.com/ 从这里可…

反汇编—switch

x64和x86分析类似 标号1的位置要计算出&#xff1a;减去(debug) / 加上(release)第一个case要等于0&#xff0c;因为第一个case在跳转表数组的0下标位置 通过1和2&#xff0c;可以知道它们应该是连续case&#xff0c;还要判断是否缺项&#xff0c;进入跳转表看 可以看到原本应…

经济型伺服电缸EMB系列

经济型伺服电缸系列特点 小型电缸&#xff0c;推力范围:5kg-1500kg 精巧设计 所有部件模块化组合&#xff0c;标准化&#xff0c;经济化 轧制滚珠丝杠&#xff0c;高效率&#xff0c;高速度 匹配经济型步进伺服电机驱动器一体化&#xff0c;可总线 can&#xff0c;erthercat等&…

NAS求变,“0成本、低门槛”的鲁大师能否脱颖而出?

互联网科技的高速发展&#xff0c;推动了全球信息爆炸的进程。如何高效地存储和使用这些海量数据成了困扰企业、乃至个人的一大难题。从U盘、到移动硬盘、再到各种网云盘、以及愈发大众化的NAS……存储解决方案也随着个人及家庭数据存储需求的不断增长而发展着。如今&#xff0…

shardingjdbc-读写分离配置

文章目录 1、application.yml2、shardingsphere.yaml3、创建实体类 User4、创建 UserMapper5、添加依赖6、读写分离测试7、事务测试 我们的主从复制已经提前搭建好&#xff1a; mysql-搭建主从复制&#xff1a;https://blog.csdn.net/m0_65152767/article/details/142214434 1…

AI最大的应用是什么,如何成为初代AGI产品经理?

❝ 在当今这个由数据驱动的时代&#xff0c;AI技术正以前所未有的速度发展&#xff0c;它不仅改变了我们与数字世界的互动方式&#xff0c;更在物理世界中掀起了一场革命。阿里巴巴集团CEO吴泳铭在2024云栖大会上的演讲&#xff0c;为我们描绘了AI技术未来的巨大潜力。他指出&a…

华为云长江鲲鹏深度赋能,大势智慧稳居“实景三维+AI”领域排头兵

本文转自长江日报大武汉客户端 走出象牙塔第10年&#xff0c;武汉大势智慧科技有限公司&#xff08;以下简称“大势智慧”&#xff09;已成长为国内三维技术创新及应用领域龙头企业&#xff0c;其自主研发的“重建大师”等三维测绘软件系统在各级测绘系统占有率达到87.5%。 这…

奇迹再现!帕金森患者6年后停药,竟能自如行走:背后的故事与启示

在医学的浩瀚星空中&#xff0c;总有一些故事如同璀璨星辰&#xff0c;照亮着患者与家属的希望之路。今天&#xff0c;我们要讲述的&#xff0c;就是一位与帕金森病抗争了6年之久的患者&#xff0c;如何在看似不可能的境遇下&#xff0c;实现了停药后自如行走的奇迹。这不仅是对…

前端——元素类型+文字样式

一、元素类型 1. 块级元素 >块级标签: div p h1~h6 ul ol li dl dt dd hr br等 还有表格标签 table 特征: 1.独占一行 不会共享一行的位置 2.不设置宽度 默认是继承父级宽度 100% 结构上没有父级那就是浏览器 3.高度不设置 默认由内容撑开 4.可…

mock虚拟接口技术

一、什么是mock mock指的就是使用mock创建出来的一个虚拟的接口 二、对于测试人员而言&#xff0c;我们为什么要使用mock 当我们进行接口测试时&#xff0c;如果对应的接口还没有开发好&#xff0c;但是我们又需要用到这个接口响应的信息&#xff0c;这个时候我们就可以使用…

学习threejs,绘制二维线

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言二、&#x1f340;绘制二维线1. ☘️…

筛子排序(SieveSort)

当你手头有了支持AVX-512&#xff08;SIMD&#xff09;的i9-11900K&#xff0c;你最想做什么&#xff1f; i9-11900K&#xff1f;现在都14代了&#xff0c;谁还用11代的&#xff1f; 但12代以上就没有AVX-512了&#xff01; AVX-512有什么特别之处&#xff1f;有了这个硬件支…

Redis 的 Java 客户端有哪些?官方推荐哪个?

Redis 官网展示的 Java 客户端如下图所示&#xff0c;其中官方推荐的是标星的3个&#xff1a;Jedis、Redisson 和 lettuce。 Redis 的 Java 客户端中&#xff0c;Jedis、Lettuce 和 Redisson 是最常用的三种。以下是它们的详细比较&#xff1a; Jedis&#xff1a; 线程安全&…

安卓13设置动态修改设置显示版本号 版本号增加信息显示 android13增加序列号

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 设置 =》关于平板电脑 =》版本号 在这里显示了系统的一些信息,但是这里面的信息并不包含序列号之类的信息,我们修改下系统设置,在这里增加上相关的序列号。 2.问题分析…

【Linux】Linux基本命令

目录 文件和目录操作&#xff1a; ls cd pwd cp mv rm mkdir rmdir touch clear history which/whereis 文件查看和编辑&#xff1a; cat less head tail vi 或 vim sz/rz echo 系统信息和管理&#xff1a; su uname hostname df free top ps ki…

高可用集群keepalived---实战案例1

目录 一、环境: 二、文件的配置 1、server1 下载keepalived 创建etc下的keepalived目录,编辑配置文件 开机启动keepalived 安装Nginx 启动keepalived 2、server2 下载keepalived 创建etc下的keepalived目录,编辑配置文件 开机启动keepalived 安装Nginx 启动keepali…

软件企业毛利率正在变得越来越低

软件开发毛利率逐渐降低的现象可能受到多种因素的影响&#xff1a; 市场竞争加剧&#xff1a;随着软件行业的快速发展&#xff0c;市场上的软件产品和服务越来越多&#xff0c;竞争也越来越激烈。为了在市场上保持竞争力&#xff0c;软件企业可能不得不降低价格&#xff0c;这直…

【word密码】word怎么限制格式,但可以修改文字?

想要限制word文件中文字的格式&#xff0c;但是又希望别人能够删除、输入文字&#xff0c;想要实现这种设置我们可以对word文件设置限制编辑。 点击word文件工具栏中的审阅 – 限制编辑&#xff0c;勾选上【限制对选定的样式设置格式】 然后在弹出的提示框中&#xff0c;输入我…

LDRA Testbed(TBrun)软件单元测试_常见问题及处理

系列文章目录 LDRA Testbed软件静态分析_操作指南 LDRA Testbed软件静态分析_自动提取静态分析数据生成文档 LDRA Testbed软件静态分析_Jenkins持续集成&#xff08;自动静态分析并用邮件自动发送分析结果&#xff09; LDRA Testbed软件静态分析_软件质量度量 LDRA Testbed软件…