请选择 进入手机版 | 继续访问电脑版
查看: 109|回复: 0

一文详解Python如何优雅地对数据进行分组

[复制链接]

2198

主题

0

回帖

7027

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
7027
发表于 2022-10-9 02:22:37 | 显示全部楼层 |阅读模式
假设我们有这样一种数据:
  1. data = [
  2.     ("apple", 30), ("apple", 35),
  3.     ("apple", 32), ("pear", 60),
  4.     ("pear", 32), ("pear", 60),
  5.     ("banana", 102), ("banana", 104)
  6. ]

  7. # 我们希望变成如下格式
  8. """
  9. [('apple', [30, 35, 32]), 
  10.  ('pear', [60, 32, 60]), 
  11.  ('banana', [102, 104])]
  12. """
复制代码
如果是你的话,你会怎么做呢?很容易想到的一种解决方案是构造一个字典:
  1. data = [
  2.     ("apple", 30), ("apple", 35),
  3.     ("apple", 32), ("pear", 60),
  4.     ("pear", 32), ("pear", 60),
  5.     ("banana", 102), ("banana", 104)
  6. ]

  7. data_dict = {}
  8. for name, count in data:
  9.     if name not in data_dict:
  10.         data_dict[name] = []
  11.     data_dict[name].append(count)
  12. print(data_dict)
  13. """
  14. {'apple': [30, 35, 32], 
  15.  'pear': [60, 32, 60], 
  16.  'banana': [102, 104]}
  17. """
  18. print(list(data_dict.items()))
  19. """
  20. [('apple', [30, 35, 32]), 
  21.  ('pear', [60, 32, 60]), 
  22.  ('banana', [102, 104])]
  23. """
复制代码
这种方案完全没有问题,不外我们还可以写的更优雅一些,也就是使用字典的 setdefault 方法:
  1. data = [
  2.     ("apple", 30), ("apple", 35),
  3.     ("apple", 32), ("pear", 60),
  4.     ("pear", 32), ("pear", 60),
  5.     ("banana", 102), ("banana", 104)
  6. ]

  7. data_dict = {}
  8. for name, count in data:
  9.     # setdefault(k, v) 含义如下
  10.     # 当 k 不存在时,将 k: v 设置在字典中,并返回 v
  11.     # 当 k 存在时,直接返回 k 对应值
  12.     data_dict.setdefault(name, []).append(count)

  13. print(list(data_dict.items()))
  14. """
  15. [('apple', [30, 35, 32]), 
  16.  ('pear', [60, 32, 60]), 
  17.  ('banana', [102, 104])]
  18. """
复制代码
setdefault 是一个非常方便的方法,但是使用频率却不怎么高,或者说该方法不太让人喜欢。主要是每次调用都要给一个初始值,好比代码中的空列表 []。另外这里的初始值可以任意,如果你希望添加的时候还能实现去重效果,那么就将空列表换成空集合即可。
或者我们还可以使用 defaultdict,它位于 collections 模块中。
  1. from collections import defaultdict

  2. data = [
  3.     ("apple", 30), ("apple", 35),
  4.     ("apple", 32), ("pear", 60),
  5.     ("pear", 32), ("pear", 60),
  6.     ("banana", 102), ("banana", 104)
  7. ]

  8. # 里面接收一个 callable
  9. # 当访问的 k 不存在时,返回 callable 调用之后的值
  10. data_dict1 = defaultdict(list)
  11. for name, count in data:
  12.     data_dict1[name].append(count)

  13. print(list(data_dict1.items()))
  14. """
  15. [('apple', [30, 35, 32]), 
  16.  ('pear', [60, 32, 60]), 
  17.  ('banana', [102, 104])]
  18. """

  19. # 也可以指定为 set
  20. data_dict2 = defaultdict(set)
  21. for name, count in data:
  22.     data_dict2[name].add(count)

  23. print(list(data_dict2.items()))
  24. """
  25. [('apple', {32, 35, 30}), 
  26.  ('pear', {32, 60}), 
  27.  ('banana', {104, 102})]
  28. """
复制代码
总的来说,defaultdict 和字典的 setdefault 方法非常类似,我们使用 setdefault 即可。
当然啦,关于分组,还有一种特殊情况,就是词频统计。假设我们想统计可迭代对象中,每个元素出现的次数该怎么做呢?
  1. data = ["apple", "apple", "apple",
  2.         "pear", "pear", "pear",
  3.         "banana", "banana"]

  4. data_dict = {}
  5. for item in data:
  6.     # 此处不能使用 setdefault,因为它是函数
  7.     # .setdefault(item, 0) += 1 是不符合语法规则的
  8.     if item not in data_dict:
  9.         data_dict[item] = 0
  10.     data_dict[item] += 1

  11. print(data_dict)
  12. """
  13. {'apple': 3, 'pear': 3, 'banana': 2}
  14. """

  15. # 或者使用 defaultdict
  16. from collections import defaultdict
  17. data_dict = defaultdict(int)
  18. for item in data:
  19.     data_dict[item] += 1
  20. print(data_dict)
  21. """
  22. defaultdict(<class 'int'>, 
  23.             {'apple': 3, 'pear': 3, 'banana': 2})
  24. """
复制代码
然而说到词频统计,我们还可以使用 collections 下的 Counter 类。
  1. from collections import Counter

  2. data = ["apple", "apple", "apple",
  3.         "pear", "pear", "pear",
  4.         "banana", "banana"]

  5. data_dict = Counter(data)
  6. # 直接搞定,Counter 已经包含了我们之前的逻辑
  7. print(data_dict)
  8. """
  9. Counter({'apple': 3, 'pear': 3, 'banana': 2})
  10. """
  11. # Counter 继承 dict,除了支持字典操作之外
  12. # 还提供了很多其它操作,其中一个就是 most_common
  13. # 用于选择出现频率最高的几个元素
  14. print(data_dict.most_common(2))
  15. """
  16. [('apple', 3), ('pear', 3)]
  17. """
复制代码
还是很简单的。
到此这篇关于一文详解Python如何优雅地对数据进行分组的文章就介绍到这了,更多相关Python数据分组内容请搜索趣UU以前的文章或继续浏览下面的相关文章希望大家以后多多支持趣UU!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
打赏作者
  • 0
  • 0
  • 0
  • 0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表