简体   繁体   English

Python 3有效地迭代列表的字典

[英]Python 3 efficiently iterating over a dictionary of list

I have working code that classifies data based on rules inside a dictionary of list. 我有工作代码,根据列表字典中的规则对数据进行分类。 I want to know if it is possible to make the code more efficient by getting rid of the nested for loops using list/dictionary comprehensions or .values(). 我想知道是否可以通过使用list / dictionary comprehensions或.values()删除嵌套的for循环来提高代码的效率。

import pandas as pd


df=pd.DataFrame({'Animals': [ 'Python', 'Anaconda', 'Viper', 'Cardinal',
                 'Trout', 'Robin', 'Bass', 'Salmon', 'Turkey', 'Chicken'],
                 'Noise': ['Hiss','SSS','Hisss','Chirp','Splash','Chirp', 
                 'Gulp','Splash','Gobble','Cluck'],
                 })


snakenoise =['Hiss','SSS','Hisss', 'Wissss', 'tseee']
birdnoise =['Chirp', 'squeak', 'Cluck', 'Gobble']
fishnoise =['Splash', 'Gulp', 'Swim']


AnimalDex = {'Snake':['0', 'slither',snakenoise],
              'Bird':['2','fly', birdnoise],
              'Fish':['0','swim',fishnoise],
              }

df['movement'] = ''

for key, value in AnimalDex.items():
    for i in range(len(AnimalDex[key][2])):
        df.loc[df.Noise.str.contains(AnimalDex[key][2][i]),'movement'] = AnimalDex[key][1]

print (df)

Here is the output 这是输出

    Animals   Noise movement
0    Python    Hiss  slither
1  Anaconda     SSS  slither
2     Viper   Hisss  slither
3  Cardinal   Chirp      fly
4     Trout  Splash     swim
5     Robin   Chirp      fly
6      Bass    Gulp     swim
7    Salmon  Splash     swim
8    Turkey  Gobble      fly
9   Chicken   Cluck      fly

If you just use the values instead of the keys and indexes, you can really simplify your loop. 如果您只使用值而不是键和索引,则可以真正简化循环。

for animal in AnimalDex.values():
    for value in animal[2]:
        df.loc[df.Noise.str.contains(value),'movement'] = animal[1]

Efficiency does not come from rewriting loops as comprehensions, since comprehensions mainly provide a nicer syntax for loops. 效率不是来自重写循环作为理解,因为理解主要为循环提供更好的语法。 Rather, it's the efficiency of the data structure lookups that is important. 相反,重要的是数据结构查找的效率。 The problem is that df.Noise.str.contains(AnimalDex[key][2][i]) performs brute-force matching. 问题是df.Noise.str.contains(AnimalDex[key][2][i])执行强力匹配。

If your goal is to merge the movements defined in AnimalDex into the df , joining according to the noise, then it pays to build a dictionary that maps noises to movements: 如果您的目标是将AnimalDex定义的移动合并到df ,根据噪声加入,那么构建将噪声映射到移动的字典是值得的:

noise_to_movement = {}
for order in AnimalDex.values():
    for noise in order[2]:
        noise_to_movement[noise] = order[1]

For comparison, here is another way to construct noise_to_movement , using incomprehensible comprehensions: 为了比较,这是使用难以理解的理解来构造noise_to_movement另一种方法:

import itertools

noise_to_movement = dict(itertools.chain(*[list(
    itertools.product(order[2], [order[1]])) for order in AnimalDex.values()
]))

Either way, once the dictionary is built, setting the 'movement' column becomes a trivial lookup: 无论哪种方式,一旦构建了字典,设置'movement'列就变成了一个简单的查找:

df['movement'] = list(noise_to_movement[n] for n in df.Noise)

To really improve performance you shouldn't be iterating through a dictionary at all. 要真正提高性能,你根本不应该遍历字典。 Instead make a pandas.DataFrame out of that data, and join the two DataFrames. 而是从该数据中创建一个pandas.DataFrame ,并加入两个DataFrame。

import pandas as pd

df = pd.DataFrame({'Animals': [ 'Python', 'Anaconda', 'Viper',   'Cardinal',
                   'Trout', 'Robin', 'Bass', 'Salmon', 'Turkey', 'Chicken'],
                   'Noise': ['Hiss','SSS','Hisss','Chirp','Splash','Chirp', 
                   'Gulp','Splash','Gobble','Cluck']})

snakenoise =['Hiss','SSS','Hisss', 'Wissss', 'tseee']
birdnoise =['Chirp', 'squeak', 'Cluck', 'Gobble']
fishnoise =['Splash', 'Gulp', 'Swim']

noises = [(snakenoise, 'Snake', '0', 'slither'),
          (birdnoise, 'Bird', '2', 'fly'),
          (fishnoise, 'Fish', '0', 'swim')]

animal_dex = {'Animal Type': [],
              'Whatever': [],
              'Movement': [],
              'Noise': []}

for noise in noises:
    animal_dex['Noise'] += noise[0]
    animal_dex['Animal Type'] += map(lambda x: noise[1], noise[0])
    animal_dex['Whatever'] += map(lambda x: noise[2], noise[0])
    animal_dex['Movement'] += map(lambda x: noise[3], noise[0])

df1 = pd.DataFrame(animal_dex)

df = df.merge(df1, on='Noise')
df
    Animals   Noise Animal Type Movement Whatever
0    Python    Hiss       Snake  slither        0
1  Anaconda     SSS       Snake  slither        0
2     Viper   Hisss       Snake  slither        0
3  Cardinal   Chirp        Bird      fly        2
4     Robin   Chirp        Bird      fly        2
5     Trout  Splash        Fish     swim        0
6    Salmon  Splash        Fish     swim        0
7      Bass    Gulp        Fish     swim        0
8    Turkey  Gobble        Bird      fly        2
9   Chicken   Cluck        Bird      fly        2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM