редактировать: последний файл здесь
Процесс проходит через рекурсию. Pandas полезен в вашем сценарии, хотя могут быть более эффективные способы сделать это.
Мы ищем из других узлов. В вашем случае это будут узлы A и E. Как мы узнаем, что это самые дальние узлы? Просто посчитайте значения 0 и 1 во всех строках. Затем получите сумму значений 0 и 1. Кроме того, отсортируйте значения по 0. В первом случае это должно быть так:
0 1
DroveToTheMovies 4.0 1.0
AteLunchTogether 3.0 2.0
BoughtElectronics 3.0 2.0
WentToMall 2.0 3.0
BoughtClothes 2.0 3.0
FirstCase 0.0 5.0
Это означает, что 1 человек ездил в кино. Вы видите закономерность. Позже к этому человеку присоединятся люди. В первом случае мы начали с 5 человек. Но есть проблема. Как мы узнаем, был ли предыдущий человек в группе? Допустим, X ездил в кино. Теперь проверяем, пообедали ли. Скажем, Y и Z присоединились к группе, но не X. В этом случае мы проверим, входит ли последняя группа в новую группу. Итак, пока мы не дойдем до первого случая, мы добавляем все событие в массив. Итак, теперь у нас есть ветка.
Предположим, что были люди, не входящие в группу. В этом случае мы также сохранили это странное поведение. Затем мы go оттуда сейчас. В первом случае нашим начальным узлом был A; не это Б, использующий ту же технику. Таким образом, процесс будет повторяться снова.
Мои окончательные результаты были такими:
0 1
0 DroveToTheMovies Index(['A'], dtype='object')
1 AteLunchTogether Index(['A', 'B'], dtype='object')
2 BoughtElectronics Index(['A', 'B'], dtype='object')
3 WentToMall Index(['A', 'B', 'C'], dtype='object')
4 FirstCase Index(['A', 'B', 'C', 'D', 'E'], dtype='object')
5 BoughtClothes Index(['E'], dtype='object')
6 FirstCase Index(['D', 'E'], dtype='object')
Есть два FirstCase. Но вам нужно обработать эти два значения FirstCase и знать, что эта группа DE относится к первой группе FirstCase, а затем E пошел за купленной одеждой. D неизвестно, поэтому может быть отнесено к другому. Вот и все.
Первая ветка:
ABCDE ---> ABC --> AB ->A
| |->B
|
|--> C
Вторая ветка:
(first case)---> DE --> D
|-->E
Все, что вам нужно сделать, это найти, кто покинул ветки. Для первой ветви это B, C и DE. Теперь их легко вычислить. Надеюсь, это тебе поможет. Код здесь, и я предлагаю его отладить, чтобы вся идея была более ясной:
import pandas as pd
df = pd.DataFrame(
[[1, 1, 1, 0, 0],
[1, 0, 0, 0, 0],
[1, 1, 0, 0, 0],
[1, 1, 0, 0, 1],
[1, 1, 0, 0, 0]], columns=list("ABCDE"))
df.index = ['WentToMall', 'DroveToTheMovies', 'AteLunchTogether', 'BoughtClothes', 'BoughtElectronics']
first_case = pd.DataFrame(
[[1, 1, 1, 1, 1]], columns=list("ABCDE"), index=['FirstCase'])
all_case = pd.concat([first_case, df])
def case_finder(all_case):
df_case = all_case.apply(lambda x: x.value_counts(), axis=1).fillna(0)
df_case = df_case.loc[df_case[1] != 0]
return df_case.sort_values(by=1)
def check_together(x):
x = df.iloc[x]
activity = all_case.loc[x.name]
does_activity = activity.loc[activity == 1]
return activity.name, does_activity.index
def check_in(pre, now):
return pre.isin(now).all()
def check_odd(i):
act = check_together(i)[0]
who = check_together(i)[1][~check_together(i)[1].isin(check_together(i-1)[1])]
return act, who
df = case_finder(all_case)
total = all_case.shape[0]
all_acts = []
last_stable = []
while True:
for i in range(total):
act, ind = check_together(i)
if ind.size == 1:
print("Initiliazed!")
all_acts.append([act, ind])
pass
else:
p_act, p_ind = check_together(i-1)
if check_in(p_ind, ind) == True:
print("So a new person joins us!")
all_acts.append([act, ind])
else:
print("This is weird. We'll check later!")
# act, who = check_odd(i)
last_stable.append([i, p_ind])
continue
if act == 'FirstCase':
break
if len(last_stable) == 0:
print("Process done!")
break
else:
print("Update cases!")
ls_ind = last_stable[0]
all_case = all_case.drop(last_stable[0][1], axis=1)
total = all_case.shape[0]
df = case_finder(all_case)
last_stable = last_stable[1:]
print(all_acts)
x = pd.DataFrame(all_acts)