Есть фрейм данных Pandas
id parent_id result
1 0 True
2 0 False
3 1 True
4 1 False
5 2 True
6 2 False
7 4 True
8 4 True
Как рекурсивно пройти весь кадр, при этом если узел содержит потомков, то мне нужно выполнить операцию «ИЛИ» для всех строк потомков и выполнить операцию «И» для этого промежуточного результата и родительской строки? то есть
AND(parent['result'], OR (descendants['result']))
Итак, мне нужно получить результат этого логического выражения:
df.loc[df['id'] == 1, 'result'] AND
(df.loc[df['id'] == 3, 'result'] OR
(
df.loc[df['id'] == 4, 'result']
AND
(
df.loc[df['id'] == 7, 'result'] OR
df.loc[df['id'] == 8, 'result']
)
)
)
OR
(
df.loc[df['id'] == 2, 'result']
AND (
df.loc[df['id'] == 5, 'result'] OR
df.loc[df['id'] == 6, 'result']
)
)
@jezrael, я отредактировал сообщение
Я думаю, вам нужно создать рекурсивную функцию для обработки каждой строки в ее parent_id
, идентификации всех потомков в строке и рекурсивной их обработки. Затем выполните операцию OR
над значениями result
всех дочерних строк. Объедините результат текущей строки с результатом OR
потомков, используя AND
. Далее нужно перебрать DataFrame и применить рекурсивную функцию к каждой строке, начиная с корневых узлов; И, наконец, сохраните результат обратно в DataFrame в том же столбце.
Использование фрейма данных из OP:
import pandas as pd
df = pd.DataFrame(
{
"id": [1, 2, 3, 4, 5, 6, 7, 8],
"parent_id": [0, 0, 1, 1, 2, 2, 4, 4],
"result": [True, False, True, False, True, False, True, True],
}
)
Решение:
def traverse(df, id):
parent_result = df[df["id"] == id]["result"].iloc[0]
children = df[df["parent_id"] == id]
if children.empty:
return parent_result
return parent_result and children["id"].apply(lambda x: traverse(df, x)).any()
root_ids = df[df["parent_id"] == 0]["id"]
out = root_ids.apply(lambda x: traverse(df, x)).any()
Выход:
True
Как выглядит ожидаемый результат?