данные и мой собственный класс 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, но я не знаю, как это реализовать самостоятельно.
Да, это именно то, что я ищу. Нет, класс не наследуется от другого класса
ваш новый класс является подклассом чего-либо в настоящее время?
Нет, у класса нет родительского или дочернего класса
Я играю с этим здесь, и это быстро становится сложным, и я просто заново изобретаю плохую версию панд, что поднимает вопрос: почему бы не использовать панд? Проблема в том, что помимо того, что нужно что-то делать с __getitem__()
, вам нужно сделать класс серии в дополнение к вашему классу кадра, чтобы вы могли делать что-то вроде df['b'] + 5
. Вы не можете сделать это с обычным списком: если у вас есть [7.0,3.5,8.0,6.0] + 5
, вы получите сообщение об ошибке, поэтому вам также нужно создать новый метод mySeriesClass.__add__()
, и да, вы чувствуете, что сейчас воссоздаете панд.
Да, мне нужно воссоздать уменьшенную версию серий и фреймов данных из панд, которые в основном терпят неудачу вместо того, чтобы возвращать NaN. У меня нет большого опыта работы с пандами, поэтому я понятия не имею, как это работает внутри. Итак, мой класс DataFrame будет содержать список объектов Series?
Я так думаю, да, но опять же, это быстро становится очень сложным. Можете ли вы лучше описать, что вы пытаетесь сделать в отношении «сбоя вместо возврата NaN»? Как в этом случае и почему? Вам, вероятно, лучше либо создать подкласс от pandas и изменить одну или две вещи, либо, возможно, даже просто использовать pandas точно так, как есть, и вызывать ошибку вне его. Например, вы можете использовать pandas и попробовать любой код, который хотите, а затем проверить, содержит ли фрейм данных какие-либо NaN, и если да, то вызвать ошибку.
Не совсем уверен, что ваш вопрос касается словарей или фреймов данных... Но для диктов я бы сделал это так:
получить значение "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]>
Чтобы было ясно, вы не пытаетесь сделать это с пандами, верно? Но вы создаете свой собственный класс и хотите сделать это с помощью нового класса фреймов? Является ли ваш новый класс подклассом чего-либо?