Python3 CookBook | 数据结构和算法(二)

简介: 工作中有时会遇到这样的需求,取出数据中前面 10% 的值,或者最后 10% 的值。我们可以先对这个列表进行排序,然后再进行切片操作,很轻松的解决这个问题。但是,有没有更好的方法呢?

1、查找最大或最小的 N 个元素


工作中有时会遇到这样的需求,取出数据中前面 10% 的值,或者最后 10% 的值。

我们可以先对这个列表进行排序,然后再进行切片操作,很轻松的解决这个问题。但是,有没有更好的方法呢?

heapq 模块有两个函数 nlargest() 和 nsmallest() 可以完美解决这个问题。


In [50]: import heapq
In [51]: n = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2, 23, 45, 76]
In [52]: heapq.nlargest(3, n)
Out[52]: [76, 45, 42]
In [53]: heapq.nsmallest(3, n)
Out[53]: [-4, 1, 2]
复制代码


如果是取排在前面的 10% 应该怎么做?


heapq.nlargest(round(len(n)/10), n)
复制代码


而且,使用这两个函数还会有更好的性能,因为在底层实现里面,会先把数据进行堆排序后放入一个列表中,然后再进行后续操作。大家如果对堆数据结构感兴趣的话,可以继续进行深入研究,由于我了解的并不深,也没办法再展开了。

但是也并不是什么时候都是这两个函数效果更好,比如只取一个最大值或者最小值,那还是 min() 或 max() 效果更好;如果要查找的元素个数已经跟集合元素个数接近时,那还是用 sorted(items)[:N] 更好,具体情况具体分析吧。


2、序列中出现次数最多的元素


以前碰到这类问题时,我都会手动创建一个字典,然后以列表中元素作为 key,进而统计出 key 出现的次数,再进行比较得到出现次数最多的元素。

殊不知 collections 中就有专门为这类问题设计的类 Counter,瞬间感觉自己蠢爆了,话不多说,直接上代码。


In [54]: from collections import Counter
In [55]: w = ['a', 'b', 'c', 'd', 'a', 'a', 'b']
In [56]: w_count = Counter(w)
In [57]: w_count
Out[57]: Counter({'a': 3, 'b': 2, 'c': 1, 'd': 1})
In [58]: w_count['a']
Out[58]: 3
In [59]: top = w_count.most_common(2)
In [60]: top
Out[60]: [('a', 3), ('b', 2)]
复制代码


可以看到,Counter 返回的就是一个字典,想知道哪个元素出现几次,直接取,是不是很方便?

而且还有 most_common 函数,简直不要太棒。


3、过滤序列元素


有一个列表,如下:


In [61]: a = [1, 2, 3, 4, 5, -3]
复制代码


要求过滤所有负数。需要新建一个列表?直接一行代码搞定。


In [64]: [n for n in a if n > 0]
Out[64]: [1, 2, 3, 4, 5]
复制代码


如果要把负数替换成 0 呢?


In [67]: [n if n > 0 else 0 for n in a]
Out[67]: [1, 2, 3, 4, 5, 0]
复制代码


但是有时候过滤条件可能比较复杂,这时就需要借助于 filter() 函数了。


values = ['1', '2', '-3', '-', '4', 'N/A', '5']
def is_int(val):
  try:
    x = int(val)
      return True
  except ValueError:
    return False
ivals = list(filter(is_int, values))
print(ivals)
# Outputs ['1', '2', '-3', '4', '5']
复制代码


4、通过某个关键字将记录分组


有下面这个字典:


rows = [
  {'address': '5412 N CLARK', 'date': '07/01/2012'},
  {'address': '5148 N CLARK', 'date': '07/04/2012'},
  {'address': '5800 E 58TH', 'date': '07/02/2012'},
  {'address': '2122 N CLARK', 'date': '07/03/2012'},
  {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},
  {'address': '1060 W ADDISON', 'date': '07/02/2012'},
  {'address': '4801 N BROADWAY', 'date': '07/01/2012'},
  {'address': '1039 W GRANVILLE', 'date': '07/04/2012'},
]
复制代码


那么怎么对这个字典按照 date 进行分组呢?借助于 itertools.groupby() 函数可以解决这个问题,代码如下:


# Sort by the desired field first
rows.sort(key=itemgetter('date'))
# Iterate in groups
for date, items in groupby(rows, key=itemgetter('date')):
  print(date)
  for i in items:
    print(' ', i)
复制代码


输出结果如下:


07/01/2012
  {'address': '5412 N CLARK', 'date': '07/01/2012'}
  {'address': '4801 N BROADWAY', 'date': '07/01/2012'}
07/02/2012
  {'address': '5800 E 58TH', 'date': '07/02/2012'}
  {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}
  {'address': '1060 W ADDISON', 'date': '07/02/2012'}
07/03/2012
  {'address': '2122 N CLARK', 'date': '07/03/2012'}
07/04/2012
  {'address': '5148 N CLARK', 'date': '07/04/2012'}
  {'address': '1039 W GRANVILLE', 'date': '07/04/2012'}
复制代码


需要注意的是,groupby() 函数仅仅检查连续相同的元素,所以在分组之前,一定要先对数据,按照分组字段进行排序。如果没有排序,便得不到想要的结果。


5、映射名称到序列元素


我常常有这样的苦恼,就是有一个列表,然后通过下标来取值,取值时很认真的数所需要元素在第几个,很怕取错值。取到值后开始下面的运算。

一段时间之后,再看这段代码,感觉很陌生,已经忘了带下标的值是什么了,还需要重新看一下这个列表的由来,才找到回忆。

如果能有一个名称映射到元素上就好了,直接通过名称就可以知道元素的含义。collections.namedtuple() 函数就可以解决这个问题。


In [76]: from collections import namedtuple
In [77]: subscriber = namedtuple('Subscriber', ['addr', 'joined'])
In [78]: sub = subscriber('jonesy@example.com', '2012-10-19')
In [79]: sub
Out[79]: Subscriber(addr='jonesy@example.com', joined='2012-10-19')
In [80]: sub.addr
Out[80]: 'jonesy@example.com'
In [81]: sub.joined
Out[81]: '2012-10-19'
复制代码


这样就可以通过名称来取值了,代码可读性也更高。

需要注意的是,这种命名元祖的方式不能直接修改其中的值,直接修改会报错


In [82]: a = namedtuple('SSS', ['name', 'shares', 'price'])
In [83]: _a = a('yongxinz', 1, 2)
In [84]: _a.shares = 4
-----------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-84-f62a5288a29a> in <module>()
> 1 _a.shares = 4
AttributeError: can't set attribute
复制代码


想要修改的话可以使用 _replace() 函数。


In [85]: _a._replace(shares=4)
Out[85]: SSS(name='yongxinz', shares=4, price=2)
复制代码


但是还有一个疑问,如果这个列表元素比较多的话,那就需要定义很多的名称,也比较麻烦,还有更好的方式吗?

未完待续。。。


目录
相关文章
|
4天前
|
机器学习/深度学习 运维 算法
【Python机器学习专栏】异常检测算法在Python中的实践
【4月更文挑战第30天】本文介绍了异常检测的重要性和在不同领域的应用,如欺诈检测和网络安全。文章概述了四种常见异常检测算法:基于统计、距离、密度和模型的方法。在Python实践中,使用scikit-learn库展示了如何实现这些算法,包括正态分布拟合、K-means聚类、局部异常因子(LOF)和孤立森林(Isolation Forest)。通过计算概率密度、距离、LOF值和数据点的平均路径长度来识别异常值。
|
4天前
|
机器学习/深度学习 数据可视化 算法
【Python机器学习专栏】t-SNE算法在数据可视化中的应用
【4月更文挑战第30天】t-SNE算法是用于高维数据可视化的非线性降维技术,通过最小化Kullback-Leibler散度在低维空间保持数据点间关系。其特点包括:高维到二维/三维映射、保留局部结构、无需预定义簇数量,但计算成本高。Python中可使用`scikit-learn`的`TSNE`类实现,结合`matplotlib`进行可视化。尽管计算昂贵,t-SNE在揭示复杂数据集结构上极具价值。
|
4天前
|
机器学习/深度学习 存储 数据采集
【Python 机器学习专栏】PCA(主成分分析)在数据降维中的应用
【4月更文挑战第30天】本文探讨了主成分分析(PCA)在高维数据降维中的应用。PCA通过线性变换找到最大化方差的主成分,从而降低数据维度,简化存储和计算,同时去除噪声。文章介绍了PCA的基本原理、步骤,强调了PCA在数据降维、可视化和特征提取上的优势,并提供了Python实现示例。PCA广泛应用在图像压缩、机器学习和数据分析等领域,但降维后可能损失解释性,需注意选择合适主成分数量及数据预处理。
|
4天前
|
机器学习/深度学习 算法 数据挖掘
【Python机器学习专栏】关联规则学习:Apriori算法详解
【4月更文挑战第30天】Apriori算法是一种用于关联规则学习的经典算法,尤其适用于购物篮分析,以发现商品间的购买关联。该算法基于支持度和置信度指标,通过迭代生成频繁项集并提取满足阈值的规则。Python中可借助mlxtend库实现Apriori,例如处理购物篮数据,设置支持度和置信度阈值,找出相关规则。
|
4天前
|
机器学习/深度学习 算法 数据挖掘
【Python机器学习专栏】层次聚类算法的原理与应用
【4月更文挑战第30天】层次聚类是数据挖掘中的聚类技术,无需预设簇数量,能生成数据的层次结构。分为凝聚(自下而上)和分裂(自上而下)两类,常用凝聚层次聚类有最短/最长距离、群集平均和Ward方法。优点是自动确定簇数、提供层次结构,适合小到中型数据集;缺点是计算成本高、过程不可逆且对异常值敏感。在Python中可使用`scipy.cluster.hierarchy`进行实现。尽管有局限,层次聚类仍是各领域强大的分析工具。
|
4天前
|
机器学习/深度学习 算法 数据挖掘
【Python 机器学习专栏】K-means 聚类算法在 Python 中的实现
【4月更文挑战第30天】K-means 是一种常见的聚类算法,用于将数据集划分为 K 个簇。其基本流程包括初始化簇中心、分配数据点、更新簇中心并重复此过程直到收敛。在 Python 中实现 K-means 包括数据准备、定义距离函数、初始化、迭代和输出结果。虽然算法简单高效,但它需要预先设定 K 值,且对初始点选择敏感,可能陷入局部最优。广泛应用在市场分析、图像分割等场景。理解原理与实现对应用聚类分析至关重要。
|
4天前
|
机器学习/深度学习 算法 前端开发
【Python机器学习专栏】集成学习算法的原理与应用
【4月更文挑战第30天】集成学习通过组合多个基学习器提升预测准确性,广泛应用于分类、回归等问题。主要步骤包括生成基学习器、训练和结合预测结果。算法类型有Bagging(如随机森林)、Boosting(如AdaBoost)和Stacking。Python中可使用scikit-learn实现,如示例代码展示的随机森林分类。集成学习能降低模型方差,缓解过拟合,提高预测性能。
|
4天前
|
机器学习/深度学习 算法 Python
【Python 机器学习专栏】随机森林算法的性能与调优
【4月更文挑战第30天】随机森林是一种集成学习方法,通过构建多棵决策树并投票或平均预测结果,具有高准确性、抗过拟合、处理高维数据的能力。关键性能因素包括树的数量、深度、特征选择和样本大小。调优方法包括调整树的数量、深度,选择关键特征和参数优化。Python 示例展示了使用 GridSearchCV 进行调优。随机森林广泛应用于分类、回归和特征选择问题,是机器学习中的重要工具。
|
4天前
|
机器学习/深度学习 算法 数据可视化
【Python机器学习专栏】决策树算法的实现与解释
【4月更文挑战第30天】本文探讨了决策树算法,一种流行的监督学习方法,用于分类和回归。文章阐述了决策树的基本原理,其中内部节点代表特征判断,分支表示判断结果,叶节点代表类别。信息增益等标准用于衡量特征重要性。通过Python的scikit-learn库展示了构建鸢尾花数据集分类器的示例,包括训练、预测、评估和可视化决策树。最后,讨论了模型解释和特征重要性评估在优化中的作用。
|
4天前
|
vr&ar Python
Python自激励阈值自回归(SETAR)、ARMA、BDS检验、预测分析太阳黑子时间序列数据
Python自激励阈值自回归(SETAR)、ARMA、BDS检验、预测分析太阳黑子时间序列数据
11 0