必会的List Comprehension (列表推导式)

python基础

浏览数:111

2019-8-25

AD:资源代下载服务

强大的List Comprehension (列表推导式)是Python中必须知道的概念。然而对于初学者来说是最具挑战性的。掌握这个概念将会在两个方面帮助你:

– 应该写更短和更高效率的代码

– 代码应该执行的更快

List Comprehension (列表推导式)比for循环快35%,比map快45% 。
注:下面将List Comprehension (列表推导式)简写为LC

什么是LC

看下面的例子:
{ x^2: x 是小于10的自然数 }
{ x: x是小于20的偶数 }
{ x: x是在 ‘MATHEMATICS’中的元音字母 }

对于初学者乍一看缺失有点懵逼,来让我们仔细观察。
每个例子包含三个方面:迭代,过滤条件,执行过程
因此,也可以认为这个只是for循环的另一种表现形式。
总之,一个for循环这样执行:

for (set of values to iterate):
  if (conditional filtering): 
    output_expression()

同样用LC形式构造一行:

 [ output_expression() for(set of values to iterate) if(conditional filtering) ]

另一个例子: { x: x是小于等于100的自然数, x的完全平方数 }
for循环写法:

for i in range(1,101):     #the iterator
   if int(i**0.5)==i**0.5: #conditional filtering
     print i               #output-expression

LC 写法:

[i for i in range(1,101) if int(i**0.5)==i**0.5]

找到一些感觉没?如果你理解了,那么LC是更简单且有效的强力工具,帮助你轻松完成很多工作。

记住:

  • 1.List循环总是返回一个结果,无论你是否用到这个结果。
  • 2.迭代和条件表达式可以嵌套多个实例。
  • 3.甚至整个List循环都可以嵌套在另一个List循环中
  • 4.多个变量可以同时迭代和操纵

应用1:平坦化矩阵(Flatten a Matrix)

目标:将一个矩阵输入,返回一个List,每一行放在一行的后面。

代码如下:

def eg1_for(matrix):
    flat = []
    for row in matrix:
        for x in row:
            flat.append(x)
    return flat

def eg1_lc(matrix):
    return [x for row in matrix for x in row ]

让我们定义一个矩阵,测试下结果:

matrix = [ range(0,5), range(5,10), range(10,15) ]
print "Original Matrix: " + str(matrix)
print "FOR-loop result: " + str(eg1_for(matrix))
print "LC result      : " + str(eg1_lc(matrix))

应用二:将一个句子中的元音字母去掉

目标:一个string作为输入,返回一个去除元音字母的string

代码如下:

def eg2_for(sentence):
    vowels = 'aeiou'
    filtered_list = []
    for l in sentence:
        if l not in vowels:
            filtered_list.append(l)
    return ''.join(filtered_list)

def eg2_lc(sentence):
    vowels = 'aeiou'
    return ''.join([ l for l in sentence if l not in vowels])

测试下:

sentence = 'My name is Aarshay Jain!'
print "FOR-loop result: " + eg2_for(sentence)
print "LC result      : " + eg2_lc(sentence)

应用三:字典推导式( Dictionary Comprehension)

目标:两个一样长度的List作为输入,返回一个字典,其中一个key,一个作为value

代码如下:

def eg3_for(keys, values):
    dic = {}
    for i in range(len(keys)):
        dic[keys[i]] = values[i]
    return dic

def eg3_lc(keys, values):
    return { keys[i] : values[i] for i in range(len(keys)) }

测试:

country = ['India', 'Pakistan', 'Nepal', 'Bhutan', 'China', 'Bangladesh']
capital = ['New Delhi', 'Islamabad','Kathmandu', 'Thimphu', 'Beijing', 'Dhaka']
print "FOR-loop result: " + str(eg3_for(country, capital))
print "LC result      : " + str(eg3_lc(country, capital))


到现在,我们都集中在LC的第一印象,即它的简洁和可读性。但这还不止!LC在各种场景中相比表现的更快。让我们进一步探讨,这里不做详细介绍。

在数据分析中的应用

对于数据分析,LC也是非常有用。
一个快速的回顾,记住LC的结构:

 [ output_expression() for(set of values to iterate) if(conditional filtering) ]

应用4:读双重LIst

可能遇到过这样的场景,在数据集中每个列都包含一个LIst。下面我们举例说明,数据集包含两列:

  • personID: 独一无二
  • skills: 每个人会的运动
Lets load the dataset:
import pandas as pd
data = pd.read_csv("skills.csv")
print data


在这里,每个人会多种不同的运动。将这些数据永在预测模型,一个好主意通常是来创建一个新的列每个运动和将其标记为1或0。
第一步是将文本转换成可以访问列表,这样单独的条目。

#Split text with the separator ';'
data['skills_list'] = data['skills'].apply(lambda x: x.split(';'))
print data['skills_list']


接下来,我们需要一个独特的运动列表来确定所需的不同的列数。这可以通过理解,独特元素构成的set(集合)。

#Initialize the set
skills_unq = set()
#Update each entry into set. Since it takes only unique value, duplicates will be ignored automatically.
skills_unq.update( (sport for l in data['skills_list'] for sport in l) )
print skills_unq


注意,这里我们使用生成器表达式,这样每个值不必动态更新和存储。现在我们使用LC将生成一个与0 – 1矩阵包含5列标记相应的运动。

#Convert set to list:
skills_unq = list(skills_unq)
sport_matrix = [ [1 if skill in row else 0 for skill in skills_unq] for row in data['skills_list']  ]
print sport_matrix


最后一步是生用Pandas DataFrame 合成:

data = pd.concat([data, pd.DataFrame(sport_matrix,columns=skills_unq)],axis=1)
print data

应用5:为多项式回归创建一列权值(Creating powers of a columns for Polynomial regression)

多项式回归算法需要多种权值相同的变量,它可以使用LC创建。多达15 – 20的相同的变量可以用在岭回归分析建模以及减少过度拟合。
让我们简单的创建一列数据集:

data2 = pd.DataFrame([1,2,3,4,5], columns=['number'])
print data2


我们定义一个变量 “deg”,包含要求的程度。我们第一步是创建一个矩阵包含不同权值的‘number’ 变量。

#Define the degree:
deg=6
#Create the matrix:
power_matrix = [ [i**p for p in range(2,deg+1) ] for i in data2['number'] ]  
print power_matrix


与前面的示例相似,现在我们将添加到dataframe。注意,在这种情况下,我们需要一个列名列表和LC可以用来容易获取它:

cols = ['power_%d'%i for i in range(2,deg+1)]
data2 = pd.concat([data2, pd.DataFrame(power_matrix,columns=cols)],axis=1)
print data2

应用6:过滤列名(Filtering column names)

个人而言,我面临过很多次这种问题,为了一个预测模型预测,选择dataframe中列的一个子集,。让我们考虑这种情况的总列:

cols = ['a', 'b', 'c', 'd', 
        'a_transform', 'b_transform', 'c_transform', 
        'd_power2', 'd_power3', 'd_power4', 'd_power5',
        'temp1', 'temp2']

可以理解为:

  • 1.a,b,c,d:原始数据列
  • 2.a_transform,b_transform,c_transform:转换后的特征,比如log,平方根等等
  • 3.d_power2,d_power3,d_power4,d_power5::相同变量的不同的权值对于多项式或者岭回归
  • 4.temp1, temp2:中间变量创建执行特定的计算
    根据正在执行的分析或使用的模型,可能有不同的用处:
  • 1.选择转换的变量
  • 2.选择不同权值相同的变量
  • 3.选择超过2个的组合
  • 4.选择所有,除了临时变量
    代码如下:
col_set1 = [x for x in cols if x.endswith('transform')]
col_set2 = [x for x in cols if 'power' in x]
col_set3 = [x for x in cols if (x.endswith('transform')) | ('power' in x)]
col_set4 = [x for x in cols if x not in ['temp1','temp2']]
print 'Set1: ', col_set1
print 'Set2: ', col_set2
print 'Set3: ', col_set3
print 'Set4: ', col_set4

End Notes

如果你已经达到这一点,我相信,现在你能够欣赏LC的重要性。你应该试着把这种技术在日常实践。尽管它可能会耗费不少时间开始,但是相信我当你进步时你会十分享受。

这篇文章能对你有帮助吗?我遗漏了什么了吗?你有一些更有趣的应用吗,您认为LC会有用吗?请分享你的评论,我们一起讨论。

英语原文链接:
https://www.analyticsvidhya.com/blog/2016/01/python-tutorial-list-comprehension-examples/

作者:CodingFish