如何避免使用'eval'函数遍历属性列表



我有一个熊猫数据帧,其中一列包含一个具有一堆属性的类。我希望将其中一些属性扩展到新列中。我有一些工作代码,但它看起来有点讨厌并使用了 eval。什么是更pythonic的方法

import pandas as pd
#Boilerplate for minimal, reproducible example
class cl:
    class inner:
        na1 = "nested atribute one"
        na2 = "nested atribute two"
    def __init__(self, name):
        self.name = name
    a1 = "atribute one"
    a2 = "atribute one"
    inner_atts = inner()

class_object1 = cl("first")
class_object2 = cl("second")
data = [class_object1,class_object2]
data_frame = pd.DataFrame(data,columns=['class object'])
####################
info_to_get = {'name','a1','a2','inner_atts.na1','inner_atts.na2'}
for x in info_to_get:
    sr = 'y.{0}'.format(x)
    data_frame['{0}'.format(x)] = data_frame['class object'].apply(lambda y: eval(sr,{'y':y}))
print(data_frame)

使用 operator.attrgetter

import operator
info_to_get = list(info_to_get)
df[info_to_get] = pd.DataFrame(df['class object'].apply(operator.attrgetter(*info_to_get)).tolist())

输出:

                             class object       inner_atts.na1  
0  <__main__.cl object at 0x7f08002d27b8>  nexted atribute one   
1  <__main__.cl object at 0x7f08002d2a90>  nexted atribute one   
        inner_atts.na2            a2   name            a1  
0  nexted atribute two  atribute one  first  atribute one  
1  nexted atribute two  atribute one    two  atribute one 

关于 pandas 首先要了解的是,它不适合存储和处理任何它无法矢量化的东西 - 有很多开销,你最好使用列表和循环来迭代它们。

也就是说,我会使用列表理解来做到这一点。

from operator import attrgetter
f = attrgetter(*info_to_get)
pd.DataFrame([f(c) for c in df['class object']], columns=info_to_get)
        inner_atts.na2    name            a2       inner_atts.na1            a1
0  nexted atribute two   first  atribute one  nexted atribute one  atribute one
1  nexted atribute two  second  atribute one  nexted atribute one  atribute one

有证据表明,使用列表合成处理不可矢量化的数据的速度最快。

最新更新