当前位置: 首页 > news >正文

数据科学的秘密武器: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.mrgr.cn/news/34877.html

相关文章:

  • python 实现word frequency functions词频函数算法
  • 卷积神经网络(CNN)图像处理与识别原理
  • 汽车HMI:UI设计进入了3D时代,设计师准备好了吗?
  • LabVIEW提高开发效率技巧----使用状态机架构
  • 低侧双向电流检测电路设计
  • GoJs 节点动态添加样式
  • AI驱动TDSQL-C Serverless 数据库技术实战营-Vanna配合ollama分析TDSQL-C Serverless 数据库
  • Mybatis基础操作
  • 奇迹再现!帕金森患者6年后停药,竟能自如行走:背后的故事与启示
  • 【Python】多个dataframe存入excel的不同的sheet表里,而不会被覆盖的方法
  • 全面解析 Apache Pulsar
  • 数据结构(顺序表)
  • lamda表达式例子全集详解
  • JAVA智能匹配真情传递红娘婚恋交友系统小程序源码
  • PyCharm远程连接AutoDL服务器实现程序调试
  • vue2实现提取字符串数字并修改数字样式(正则表达式)
  • 【linux内核】eBPF基础及应用调研
  • DeiT(ICML2021):Data-efficient image Transformer,基于新型蒸馏且数据高效的ViT!
  • 分布式锁实现与原理探究:介绍总结
  • jQuery——jQuery的基本使用