Как избежать использования функции eval для перебора списка атрибутов

У меня есть фрейм данных pandas со столбцом, содержащим класс с кучей атрибутов. Я хочу расширить некоторые из этих атрибутов в новые столбцы. У меня есть рабочий код, но он выглядит немного противно и использует eval. Каков более питонический способ сделать это

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)

Это плохой способ использования фрейма данных pandas.

cs95 07.06.2019 04:32
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
93
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Используйте 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

Доказательства предполагают вы получаете максимальное ускорение при работе с не векторизуемыми данными, используя компоновки списков.

Другие вопросы по теме