每个数据科学家都应该知道的12个Python特性!

每个数据科学家都应该知道的12个Python特性!

作为一名数据科学家,你对Python的强大功能并不陌生。从数据整理到机器学习,Python已成为数据科学事实上的语言。但是你是否利用了Python提供的所有特性?

在本文中,我们将深入探讨每个数据科学家都应该了解的12个Python特性。从推导式到数据类,这些特性将帮助你编写更高效、可读且可维护的代码。如果你想了解更多关于Python的相关内容,可以阅读以下这些文章:
探索Python强大引擎:将数据可视化提升到新高度的10个库
Python简化:使用ChatGPT进行数据可视化注释
Python:释放效率——轻松简化你的日常工作!
Mojo:比Python快35000倍的AI编程语言

01 推导

Python中的推导式是机器学习和数据科学任务的有用工具,因为它们允许以简洁且可读的方式创建复杂的数据结构。

列表推导式可用于生成数据列表,例如从一系列数字中创建平方值列表。嵌套列表推导式可用于平面化多维数组,这是数据科学中常见的预处理任务。

# list comprehension
_list = [x**2 for x in range(1, 11)]

# nested list comprehension to flatten list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

flat_list = [num # append to list
            for row in matrix # outer loop
            for num in row] # inner loop

print(_list)
print(flat_list)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[1, 2, 3, 4, 5, 6, 7, 8, 9]

字典和集合推导式分别用于创建字典和数据集。例如,字典推导可用于在机器学习模型中创建特征名称及其相应值的字典。

生成器推导式对于处理大型数据集特别有用,因为它们动态生成值,而不是在内存中创建大型数据结构。这有助于提高性能并减少内存使用。

# dictionary comprehension
_dict = {var:var ** 2 for var in range(1, 11) if var % 2 != 0}

# set comprehension
# create a set of squares of numbers from 1 to 10
_set = {x**2 for x in range(1, 11)}

# generator comprehension
_gen = (x**2 for x in range(1, 11))

print(_dict)
print(_set)
print(list(g for g in _gen))
{1: 1, 3: 9, 5: 25, 7: 49, 9: 81}
{64, 1, 4, 36, 100, 9, 16, 49, 81, 25}
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

02 枚举

enumerate是一个内置函数,允许迭代序列(例如列表或元组),同时跟踪每个元素的索引。

这在处理数据集时非常有用,因为它允许轻松访问和操作单个元素,同时跟踪其索引位置。

这里我们用enumerate迭代字符串列表,如果索引是偶数则打印出该值。

for idx, value in enumerate(["a", "b", "c", "d"]):
    if idx % 2 == 0:
        print(value)
a
c

03 Zip

zip是一个内置函数,允许并行迭代多个序列(例如列表或元组)

下面我们使用zip同时迭代两个列表x和y并对其相应的元素执行操作。

x = [1, 2, 3, 4]
y = [5, 6, 7, 8]

# iterate over both arrays simultaneously
for a, b in zip(x, y):
    print(a, b, a + b, a * b)
1 5 6 5
2 6 8 12
3 7 10 21
4 8 12 32

在本例中,它打印出和中每个元素的值x和y,它们的总和以及它们的乘积。

04 生成器

Python中的生成器是一种可迭代类型,它允许动态生成一系列值,而不是一次生成所有值并将它们存储在内存中。

这使得它们对于处理无法放入内存的大型数据集非常有用,因为数据是小块或批量处理的,而不是一次性处理的。

下面我们使用生成器函数来生成Fibonacci数列中的第一个数字n。该yield关键字用于一次生成序列中的每个值,而不是一次生成整个序列。

def fib_gen(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b


res = fib_gen(10)
print(list(r for r in res))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

05 Lambda函数

lambda是用于创建匿名函数的关键字,匿名函数是没有名称并且可以在一行代码中定义的函数。

它们对于动态定义自定义函数以进行特征工程、数据预处理或模型评估非常有用。

下面我们lambda创建一个简单的函数来从数字列表中过滤偶数。

numbers = range(10)
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)
[0, 2, 4, 6, 8]

这是在Pandas中使用lambda函数的另一个代码片段。

import pandas as pd

data = {
    "sales_person": ["Alice", "Bob", "Charlie", "David"],
    "sale_amount": [100, 200, 300, 400],
}
df = pd.DataFrame(data)

threshold = 250
df["above_threshold"] = df["sale_amount"].apply(
    lambda x: True if x >= threshold else False
)
df
sales_person   sale_amount   above_threshold
0   Alice   100   False
1   Bob   200   False
2   Charlie   300   True
3   David   400   True

06 映射、过滤、归约

函数map、filter和reduce是三个用于操作和转换数据的内置函数。

map用于将函数应用于可迭代的每个元素,filter用于根据条件从可迭代中选择元素,reduce用于将函数应用于迭代中的成对元素以产生单个结果。

下面是一个综合应用三个函数的例子,计算偶数的平方和。

numbers = range(10)

# Use map(), filter(), and reduce() to preprocess and aggregate the list of numbers
even_numbers = filter(lambda x: x % 2 == 0, numbers)
squares = map(lambda x: x**2, even_numbers)
sum_of_squares = reduce(lambda x, y: x + y, squares)


print(f"Sum of the squares of even numbers: {sum_of_squares}")
Sum of the squares of even numbers: 120

07 any和all

any和all是内置函数,允许检查可迭代中的任何或所有元素是否满足特定条件。

any和all可用于检查数据集或数据集子集是否满足某些条件。例如,它们可用于检查列中是否缺少任何值,或者列中的所有值是否在特定范围内。

下面是检查是否存在偶数值和所有奇数值的简单示例。

data = [1, 3, 5, 7]
print(any(x % 2 == 0 for x in data))
print(all(x % 2 == 1 for x in data))
False
True

08 next

next用于从迭代器中检索下一个项目。迭代器是可以迭代(循环)的对象,例如列表、元组、集合或字典。

next在数据科学中通常用于迭代迭代器或生成器对象。它允许用户从可迭代中检索下一个项目,并且对于处理大型数据集或流数据非常有用。

下面,我们定义一个生成器random_numbers(),生成0到1之间的随机数。然后,我们使用next()函数查找生成器中第一个大于0.9的数字。

import random 

def random_numbers():
    while True:
        yield random.random()

# Use next() to find the first number greater than 0.9
num = next(x for x in random_numbers() if x > 0.9)

print(f"First number greater than 0.9: {num}")
First number greater than 0.9: 0.9444805819267413

09 默认字典

defaultdict是内置类的子类dict,允许为缺失的键提供默认值。

defaultdict对于处理丢失或不完整的数据非常有用,例如在处理稀疏矩阵或特征向量时。它还可用于计算分类变量的频率。

一个例子是计算列表中项目的出现次数。如果传入default_factory的参数为int,一开始初始化键对应的值都为0。

from collections import defaultdict

count = defaultdict(int)
for item in ['a', 'b', 'a', 'c', 'b', 'a']:
    count[item] += 1

count
defaultdict(int, {'a': 3, 'b': 2, 'c': 1})

10 partial

partial是functools模块中的一个函数,它允许从预先填充了某些参数的现有函数创建新函数。

partial对于创建带有预先填充的特定参数或参数的自定义函数或数据转换非常有用。这有助于减少定义和调用函数时所需的样板代码量。

在这里,我们使用partial现有函数add创建一个新函数increment,并将其参数之一固定为值1。

调用increment(1)本质上就是调用add(1, 1)

from functools import partial

def add(x, y):
    return x + y

increment = partial(add, 1)
increment(1)
2

11 lru_cache

lru_cache是functools模块中的一个修饰函数,它允许使用有限大小的缓存来缓存函数的结果。

lru_cache对于优化计算成本较高的函数或可能使用相同参数多次调用的模型训练过程非常有用。

缓存可以帮助加快函数的执行速度并降低总体计算成本。

这是一个使用缓存有效计算Fibonacci numbers(https://en.wikipedia.org/wiki/Fibonacci_number)的示例(在计算机科学中称为记忆)

rom functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

fibonacci(1e3)
4.346655768693743e+208

12 数据类

@dataclass修饰器根据定义的属性自动类生成几个特殊方法,例如__init__,__repr__,和__eq__。

这有助于减少定义类时所需的样板代码量。dataclass对象可以表示数据点、特征向量或模型参数等。

在此示例中,dataclass用于定义Person具有三个属性的简单类:name、age和city。

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int
    city: str

p = Person("Alice", 30, "New York")
print(p)
Person(name='Alice', age=30, city='New York')

这就是本文的全部内容,感谢阅读。你还可以订阅我们的YouTube频道,观看大量大数据行业相关公开课:https://www.youtube.com/channel/UCa8NLpvi70mHVsW4J_x9OeQ;在LinkedIn上关注我们,扩展你的人际网络!https://www.linkedin.com/company/dataapplab/

原文作者:Benedict Neo
翻译作者:Dou
美工编辑:过儿
校对审稿:Chuang
原文链接:https://medium.com/bitgrit-data-science-publication/12-python-features-every-data-scientist-should-know-1d233dbaab0c