Лучший способ найти порядок временных рядов из матрицы групп - PullRequest
0 голосов
/ 29 мая 2020

Есть ли стандартный способ сделать это?

В основном у меня есть несколько пользователей, которые выполняли действия вместе и отделялись как группа. Мы не знаем порядка событий, но можем вывести их:

                      A B C D E
 WentToMall           1 1 1 0 0
 DroveToTheMovies     1 0 0 0 0
 AteLunchTogether     1 1 0 0 0     
 BoughtClothes        1 1 0 0 1
 BoughtElectronics    1 1 0 0 0

Правило состоит в том, что после этого они не могут сойтись вместе. Таким образом, временной ряд будет выглядеть так:

Время 0 - это всегда все они вместе, тогда самая большая «группировка» разделяется на «WentToMall», где мы получаем A, B, C и D, E

Отсюда похоже, что AB отделилась от C, а AB переходит к «AteLunchTogether, BoughtClothes, BoughtElectronics». Когда-то во время «купленной одежды» кажется, что E отделилась от D. Наконец, A и B отделились в конце как A «Поехал в кино».

Если возможно, я бы хотел также показать это визуально, возможно, с узлами, показывающими количество событий, разделяющих разделение (что могло бы выглядеть):

ABCDE   ---> ABC --> AB  ->A
 |             |      |->B 
 |             |
 |             |--> C
 |
 |
 |---> DE --> D
       |-->E

Возникает проблема, иногда вы получаете временные точки, которые `` трудно оценить '' или которые появляются противоречивые и не умещаются по минимальному количеству столбцов. Я тоже не знаю, что с этим делать. Мне даны «веса» для действий, так что я могу принять решение на основе этого, или я думаю, сгенерируйте все версии графика.

Я думал, может быть, о рекурсии для выполнения поиска или подобном?

1 Ответ

1 голос
/ 29 мая 2020

редактировать: последний файл здесь

Процесс проходит через рекурсию. 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...