发表日期:2019-10-27
数据科学方向上必知必会的 3 个 Python “酷炫功能”
—— 你是不是还没意识到,纯 Python 的语言特性本身就能给你带来哪些神奇的玩法?
作者:Dario Radečić
随着数据科学和机器学习领域的不断发展,最前沿的技术可谓层出不穷,但它们终究都是建立在 Python 的基础上的。
最近,微博上出了篇文章,说是一个英伟达工程师小姐姐,发了套名叫 python-is-cool 的“ Python 酷炫功能合集”,“里面都是‘从前没发现,或者从前不太敢用’的机器学习技巧”。或许是因为合集里的东西太过于基础,这篇文章被大 V 们嘲笑为标题党,因为“里面没有任何一条是‘机器学习’技巧,都是 Python 语法”……
好吧,我承认我也笑了。但笑过之后,我不禁扪心自问了一下,难道基础语法就没什么用吗?
不是的。
磨刀不误砍柴工
诚然,如果只会基础语法,拿不出什么像样的实用技术,那不管是作为机器学习工程师、还是数据分析师,肯定是拿不出手的。但对于刚进入这一领域的新人来说,基础语法的熟练掌握,语言特性的灵活使用,还是具有相当重要的意义——最起码,能帮你减轻许多工作量。
是啊,我也是一个数据科学方面的新人。Pandas 牛逼,Numpy 超神,这我都知道。但你有没有想过,这些库你会不会用得太早了?你是不是还没意识到,纯 Python 的语言特性本身就能给你带来哪些神奇的玩法?
如果你也有类似的想法,那么今天这篇文章一定适合你。
图片来源:Unsplash
今天要介绍的内容其实是我在日常的数据分析工作中经常用到的几个纯 Python 语言特性或者函数。平时我在整个数据准备过程中都会超频繁地使用它们(大部分是为了数据清洗),甚至在可视化绘图前的数据整合偶尔也会用到。
译注:对于已经将这些技巧烂熟于心的大佬,欢迎在下面留言嘲笑我。
对于正在学习的新人,我个人建议你可以把这些技巧用到你自己的项目中去。虽然它们并不会带来多少运行速度或是效率提升,但起码你不用自己从头实现这些功能,能省下大把的编码时间。那么,话不多说,让我们从第一个特性开始吧!
图片来源:GIPHY
1. Lambda 函数
在数据科学工作中,Lambda 函数必须用强大来形容。虽然有的时候你并不是非得要用到它们——比如对多列数据都只用同一种方式进行清理之类的——但这种情况并不常见,你往往需要针对每一列属性,都使用不同的逻辑进行清理。
这就是 Lambda 函数大显身手的时候啦。确切地说,Lambda 函数能让你创造出一个“匿名”的函数。这基本上意味着你能快速生成并使用一些临时需要的函数,而不必想方设法用 def
关键字来定义一堆可能只会被调用一次的函数。
话虽这么说,但请记住,lambda 函数主要设计来用作单行函数使用的——因此你应该只用它来进行简单的工作。如果你需要处理复杂的逻辑,那你还是应该用上正常的函数定义。
好,介绍了这么多,下面请看这两个具体实例。在这些例子里你能看出,如果不需要为每一个逻辑都写一个函数定义,你能省下多少的时间。
在实际工作中,我们一般并不会真的像第一个例子里这样写“平方函数”,但这段代码基本上能体现出 lambda 函数的性质:
# 通常的函数定义
def square_number(x):
res = x ** 2
return res
# lambda 函数
square = lambda x: x ** 2
# 运行一下看看结果
print('square_number(4): {}'.format(square_number(4)))
print('square lambda: {}'.format(square(4)))
>>> square_number(4): 16
>>> square lambda: 16
上面这段代码,用两种方式定义了同一个“平方”的函数逻辑。当然,结果是一样的。但如果只用一行表达式来定义,看起来多舒服呀。
下一个例子,是检查一个数字是否是偶数:
# 通常的函数定义
def is_even(x):
if x % 2 == 0:
return True
else:
return False
# lambda 函数
even = lambda x: x % 2 == 0
# 运行一下看看结果
print('is_even(4): {}'.format(is_even(4)))
print('is_even(3): {}'.format(is_even(3)))
print('even(4): {}'.format(even(4)))
print('even(3): {}'.format(even(3)))
>>> is_even(4): True
>>> is_even(3): False
>>> even(4): True
>>> even(3): False
和第一个例子一样,这里也用两种方式实现了相同的逻辑。你对比一下看看吧。
2. 列表推导式
用最简单的话来说,列表推导式(list comprehension)能让你使用一些简单的符号就生成符合特定要求的列表对象。你可以把它想象成是在一对中括号里的单行循环语句,循环的结果将会被放到生成的列表对象中。
在进行特征工程(feature engineering)的时候,我会相当频繁地用到列表推导式。比如,在垃圾邮件检测中,我对邮件标题进行分析,想要知道在垃圾邮件的标题里出现问号的情况是不是会更多。使用列表推导式就能很方便地完成这个任务——我只需要从所有对象的列表中生成符合要求的新列表对象即可。
差不多就是这样。理论上的东西也不需要唠叨太多,请直接看下面的例子吧。
假设我需要从一个列表中,找到所有首字母为 A 的元素。下面我先是写了一个函数来读取、检查元素、构建列表并返回所需的对象,然后又用列表推导式实现了一下相同的逻辑。(你觉得哪种写法写起来更快呢?)
lst = ['Acer', 'Asus', 'Lenovo', 'HP']
# 使用函数来实现
def starts_with_a(lst):
valids = []
for word in lst:
if word[0].lower() == 'a':
valids.append(word)
return valids
# 使用列表生成式
lst_comp = [word for word in lst if word[0].lower() == 'a']
# 运行一下看看结果
print('starts_with_a: {}'.format(starts_with_a(lst)))
print('list_comprehension: {}'.format(lst_comp))
>>> starts_with_a: ['Acer', 'Asus']
>>> list_comprehension: ['Acer', 'Asus']
刚开始,这个语法可能会让你看着有点晕。但如果你天天用它,你就能很轻松地看透它所包含的复杂逻辑。
3. Zip 函数
Zip 函数作为 Python 的内置函数,确实很少被人用到。从数据科学的角度来说,它能让你同时迭代两个或多个列表。这在处理时间与日期的时候会非常好用。
举个例子。在我日常工作中,如果我要处理的属性之一是某些事件的开始时间,而另外一个属性代表着该事件的结束时间。为方便进一步的研究,往往会需要计算这事件的时长,也就是两个数据的差。这时候,你会发现用 zip
是最方便的处理方式。
下面这段代码演示的是对两个数组(列表对象)的元素逐一相减,求出它们的差:
sales_north = [350, 287, 550, 891, 241, 653, 882]
sales_south = [551, 254, 901, 776, 105, 502, 976]
for s1, s2 in zip(sales_north, sales_south):
print(s1 - s2)
>>> -201
33
-351
115
136
151
-94
看看这多么简单啊。如果你需要把同样的逻辑扩展到第三个数组中去,你只需要增加一个 s3
循环变量,并在 zip
的参数中引入第三个数组的名称。
结束语
纯 Python 就已经相当强大了,请务必确保自己对它的能力有足够的了解。你并不需要为每件事情都弄一个专门的库来完成——我的意思是,用库里做好的函数当然也会有所帮助,但用好 Python 本身的特性将会让你成为一个更优秀的程序员。
多加练习,掌握这些技巧,将它们用在你的日常工作中。不论是为了工作,为了学习,还是只为了好玩,你都不会后悔的。
亲爱的读者,你们有没有什么想法?你是否觉得还有其他的纯 Python 特性是数据分析师必须掌握的呢?欢迎在下面留言分享!
图片来源:Unsplash
(本文已投稿给「优达学城」。 原作: Dario Radečić 译者:欧剃 转载请保留此信息)
编译来源: https://towardsdatascience.com/3-essential-python-skills-for-data-scientists-b642a1397ae3
标签:Udacity、Translate、Python、Data-Science