Переопределить оператор dict square [] для выполнения операций равенства

данные и мой собственный класс DataFrame, который принимает dict в качестве параметра, подобного этому.

frame = {
    "a": ["X4E", "T3B", "F8D", "C7X"],
    "b": [7.0, 3.5, 8.0, 6.0],
    "c": [5, 3, 1, 10],
    "d": [False, False, True, False]
}

df = DataFrame(frame)

Как можно переопределить метод __getitem__ для диктов, чтобы разрешить такие действия, как

res = df[(df["b"] + 5.0 > 10.0)]["a"]

который вернет все случаи, когда b + 5,0 больше 10,0. Как список/серия логических значений. Это в конечном итоге распространится на что-то вроде этого

res = df[(df["b"] + 5.0 > 10.0) & (df["c"] > 3) & ~df["d"]]["a"]

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

Чтобы было ясно, вы не пытаетесь сделать это с пандами, верно? Но вы создаете свой собственный класс и хотите сделать это с помощью нового класса фреймов? Является ли ваш новый класс подклассом чего-либо?

scotscotmcc 20.11.2022 18:21

Да, это именно то, что я ищу. Нет, класс не наследуется от другого класса

raiyan 20.11.2022 18:41

ваш новый класс является подклассом чего-либо в настоящее время?

scotscotmcc 20.11.2022 18:42

Нет, у класса нет родительского или дочернего класса

raiyan 20.11.2022 18:45

Я играю с этим здесь, и это быстро становится сложным, и я просто заново изобретаю плохую версию панд, что поднимает вопрос: почему бы не использовать панд? Проблема в том, что помимо того, что нужно что-то делать с __getitem__(), вам нужно сделать класс серии в дополнение к вашему классу кадра, чтобы вы могли делать что-то вроде df['b'] + 5. Вы не можете сделать это с обычным списком: если у вас есть [7.0,3.5,8.0,6.0] + 5, вы получите сообщение об ошибке, поэтому вам также нужно создать новый метод mySeriesClass.__add__(), и да, вы чувствуете, что сейчас воссоздаете панд.

scotscotmcc 20.11.2022 18:55

Да, мне нужно воссоздать уменьшенную версию серий и фреймов данных из панд, которые в основном терпят неудачу вместо того, чтобы возвращать NaN. У меня нет большого опыта работы с пандами, поэтому я понятия не имею, как это работает внутри. Итак, мой класс DataFrame будет содержать список объектов Series?

raiyan 20.11.2022 19:03

Я так думаю, да, но опять же, это быстро становится очень сложным. Можете ли вы лучше описать, что вы пытаетесь сделать в отношении «сбоя вместо возврата NaN»? Как в этом случае и почему? Вам, вероятно, лучше либо создать подкласс от pandas и изменить одну или две вещи, либо, возможно, даже просто использовать pandas точно так, как есть, и вызывать ошибку вне его. Например, вы можете использовать pandas и попробовать любой код, который хотите, а затем проверить, содержит ли фрейм данных какие-либо NaN, и если да, то вызвать ошибку.

scotscotmcc 20.11.2022 19:08
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
7
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Не совсем уверен, что ваш вопрос касается словарей или фреймов данных... Но для диктов я бы сделал это так:

получить значение "b", которое является списком в вашем примере, перебрать список, и если значение + 5 больше 10, вернуть true, иначе вернуть false.

Этот код должен работать:

for x in range(len(frame["b"])):
    if frame["b"][x] + 5 > 10:
        print("True")
    else:
        print("False")

Извините, если я неправильно понял, о чем вы просили.

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

Это очень упрощенно, но вам нужно определить __getitem__ в своем классе DataFrame, а также иметь какой-то тип Column (аналогично pd.Series в пандах).

Прямо сейчас это реализует только __add__, но чтобы добраться туда, куда вы хотите, вам нужно будет реализовать другие операторы сравнения (и проверить типы ваших Column), а также некоторый механизм индексации. Надеюсь это немного поможет!

class Column:
    def __init__(self, l):
        self.l = l

    def __str__(self):
        return f"<Column {self.l}>"

    def __add__(self, o):
        return Column([n + o for n in self.l])


class DataFrame:
    def __init__(self, data):
        self.data = {}

        for key, val in data.items():
            if isinstance(val, list):
                self.data[key] = Column(val)

    def __str__(self):
        s = "<DataFrame\n"

        for key, val in self.data.items():
            s += f"\t{key}: {val}\n"

        s += ">"

        return s

    def __getitem__(self, key):
        return self.data[key]


frame = {
    "a": ["X4E", "T3B", "F8D", "C7X"],
    "b": [7.0, 3.5, 8.0, 6.0],
    "c": [5, 3, 1, 10],
    "d": [False, False, True, False],
}


df = DataFrame(frame)

print(df)
print(df["b"])
print(df["b"] + 5.0)

Вывод

<DataFrame
    a: <Column ['X4E', 'T3B', 'F8D', 'C7X']>
    b: <Column [7.0, 3.5, 8.0, 6.0]>
    c: <Column [5, 3, 1, 10]>
    d: <Column [False, False, True, False]>
>
<Column [7.0, 3.5, 8.0, 6.0]>
<Column [12.0, 8.5, 13.0, 11.0]>

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