Определение оптимальной конфигурации группы с помощью панд - PullRequest
0 голосов
/ 25 октября 2018

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

Пример ввода DF

time_together = 5184000 (60 days)

person_name  start_date  end_date    cut_off (start + time_together)
sally        1540627200  1545638400  1545811200
john         1543046400  1548316800  1548230400
edgar        1548316800  1553414400  1553500800

В настоящее время у меня есть даты начала и окончания в метках времени Unix во фрейме данных pandas.Я рассчитал время отключения, которое является временем начала + минимальная продолжительность.Затем я проверяю посещаемость каждого человека по отсечке, если она меньше, чем я говорю, они сформируют действительную группу (см. Код ниже)

df_new = pd.DataFrame()
for i in range(len(df.index)):
    start_range = (df.loc[i,'cutoff'] - df['start_timestamp'] > 0)
    end_range = (df.loc[i,'cutoff'] < df['end_timestamp'])
    df_new['%s%s' % (df.loc[i,'Soldier_SSN'],i)] = start_range & end_range

Проблема в том, что у меня теперь есть матрица bools, и янеобходимо сгенерировать вывод с именем группы.(см. ниже для идеального выхода).

Токовый выход DF:

  sally  john  edgar
0 True   True  False
1 True   True  False
2 False  False False

Потому что Салли и Джон были вместе в течение минимального времени.Они сформировали бы группу, а Эдгар - нет.

В идеале выводом будет список списков [[person1, person2, person5], [person3, person4]]

Это такжеПривет медленно, поэтому любые предложения о том, как ускорить это было бы здорово.

1 Ответ

0 голосов
/ 26 октября 2018

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

  1. Найдите все пары людей, которые перекрываются друг с другом в течение минимального периода времени
  2. «Конденсировать» список пар в группы

Для первой задачи простой метод состоит в том, чтобы просто пройтись по каждому человеку и проверить, достаточно ли перекрывается любой другой человек.

Начиная с тестового фрейма данных (псевдослучайные времена и произвольные имена):

index  person_name  start_date  end_date
0   Angelina    1510568169  1523357075
1   Na  1555533506  1568322412
2   Twyla   1558758901  1571547807
3   Wilfredo    1551369432  1564158338
4   Estefana    1515025466  1527814372

Мы можем найти пары с:

pairs = []
for i in range(len(test.index)):
    for j in range(len(test.index)-i-1):
        if (min(test.loc[i]['end_date'], test.loc[i+j+1]['end_date']) 
        - max(test.loc[i]['start_date'], test.loc[i+j+1]['start_date']) 
        >= (min_time_together)):
            pairs.append([test.loc[i]['person_name'], test.loc[i+j+1]['person_name']])

Это сгенерирует вывод:

[['Angelina', 'Estefana'],
 ['Na', 'Twyla'],
 ['Na', 'Wilfredo'],
 ['Twyla', 'Wilfredo']]

Чтобы "сжать" этот список пар, нужно использовать теорию графов, которая, если честно, я не эксперт по НО, но вот удивительный ответ на связанный вопрос StackOverflow (Очень интересная тема и много хорошей информации на этой странице).Если мы используем функцию condenseBK из этого ответа в нашем списке списков, мы получаем окончательный результат:

#condenseBK(*pairs)
[['Angelina', 'Estefana'], ['Na', 'Twyla', 'Wilfredo']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...