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

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

相关文章:

  • golang学习笔记10-循环结构
  • 黎巴嫩通信设备连环爆炸之谜——网络+供应链攻击
  • 单元测试和unittest框架(超详细总结)
  • ubuntu配置libtorch CPU版本
  • 基本定时器的预分频器和技术周期的计算
  • STM32与51单片机的区别:是否应该直接学习STM32?
  • 推荐一款开源的Redis桌面客户端
  • uniapp打字效果流式输出
  • 【machine learning-13-线性回归的向量化】
  • AUTOSAR_EXP_ARAComAPI的5章笔记(11)
  • ubuntu中Python解释器位置
  • C++性能分析easy_profiler
  • IntelliJ IDEA 2024.1.4 (Ultimate Edition)找不到Add Framework Support解决方法
  • Python爬虫之requests模块(一)
  • 全栈开发(三):springBoot3中使用mybatis-plus
  • 二分查找算法(4) _搜索插入位置
  • maxwell 输出消息到 redis
  • 【计算机基础】用bat命令将Unity导出PC包转成单个exe可执行文件
  • SQL面试常见题目
  • [uni-app]小兔鲜-01项目起步
  • Spring Boot 学习之路 -- 配置项目
  • C# 中yield 的使用详解
  • 【Python】多个dataframe存入excel的不同的sheet表里,而不会被覆盖的方法
  • 【ansible】role流程实验
  • 块匹配算法简介(上)
  • 腾讯云负载均衡ssl漏洞(CVE-201602183)解决
  • seL4 Capabilities(翻自官网)(一)
  • 【系统架构设计师】专业英语90题(附答案详解)
  • 代码随想录算法训练营第40天 动态规划part07| 题目: 198.打家劫舍 、 213.打家劫舍II 、 337.打家劫舍III
  • 软件设计-开闭原则