#python #pandas #dataframe #indexing
#python #pandas #фрейм данных #индексирование
Вопрос:
Чтобы сообщать о встречах, я пытаюсь создать новый столбец для добавления в существующий фрейм данных следующим образом;
import pandas as pd
df = pd.DataFrame({'appt_start': ['2020-07-02 09:00:00', '2020-07-03 15:00:00', '2020-07-03 15:00:00', '2020-07-06 04:00:00', '2020-07-06 07:00:00', '2020-07-06 07:00:00'],
'name': ['John', 'Mark', 'Sam', 'Sam', 'John', 'Sue'],
'appt_end': ['2020-07-02 12:55:00', '2020-07-03 17:10:00', '2020-07-03 20:25:00', '2020-07-06 07:50:00', '2020-07-06 07:20:00', '2020-07-06 09:05:00']})
Применяемая логика:
подсчитайте количество вхождений, в которых существующее datetime в appt_start
столбце меньше или равно текущему и всем предыдущим datetime в appt_end
столбце
Предполагаемый результат
appt_start name appt_end count
0 2020-07-02 09:00:00 John 2020-07-02 12:55:00 1
1 2020-07-03 15:00:00 Mark 2020-07-03 17:10:00 1
2 2020-07-03 15:00:00 Sam 2020-07-03 20:25:00 2
3 2020-07-06 04:00:00 Sam 2020-07-06 07:50:00 1
4 2020-07-06 07:00:00 John 2020-07-06 07:20:00 2
5 2020-07-06 07:00:00 Sue 2020-07-06 09:05:00 3
Ответ №1:
Дурацкое вещание
m = df['appt_start'].values[:, None] <= df['appt_end'].values
m[np.triu_indices(len(m), 1)] = False
df['count'] = m.sum(1)
Пояснения
Создайте логическую маску, используя numpy broadcasting, сравнивая каждое значение в appt_start
столбце с каждым значением в appt_end
столбце.
>>> m
array([[ True, False, False, False, False, False],
[False, True, False, False, False, False],
[False, True, True, False, False, False],
[False, False, False, True, False, False],
[False, False, False, True, True, False],
[False, False, False, True, True, True]]
Теперь получите индексы верхней треугольной матрицы, начинающиеся на одну диагональ вправо в приведенной выше булевой маске m
, с помощью np.triu_indices
with offset 1
и обновите значения в этих позициях до False
.
Почему мы устанавливаем эти значения False
?
Логические значения главной диагонали в маске представляют результат сравнения datetime
значений в appt_start
appt_end
столбцах и в текущей строке, а все предыдущие логические значения из главной диагонали являются результатом сравнения текущего значения даты и времени в appt_start
со всеми предыдущими datetime
значениями в appt_end
:
>>> m
array([[ True, False, False, False, False, False],
[False, True, False, False, False, False],
[False, True, True, False, False, False],
[False, False, False, True, False, False],
[False, False, False, True, True, False],
[False, False, False, True, True, True]])
Затем возьмите sum
с собой axis=1
, чтобы подсчитать количество вхождений, в которых существующее datetime в appt_start
столбце меньше или равно текущему и всем предыдущим datetime в appt_end
столбце:
>>> df
appt_start name appt_end count
0 2020-07-02 09:00:00 John 2020-07-02 12:55:00 1
1 2020-07-03 15:00:00 Mark 2020-07-03 17:10:00 1
2 2020-07-03 15:00:00 Sam 2020-07-03 20:25:00 2
3 2020-07-06 04:00:00 Sam 2020-07-06 07:50:00 1
4 2020-07-06 07:00:00 John 2020-07-06 07:20:00 2
5 2020-07-06 07:00:00 Sue 2020-07-06 09:05:00 3
Комментарии:
1. Это было великолепно! Не могли бы вы кратко объяснить свой код
2. приветствия. Кажется, я понимаю до последней части ‘… Наконец, возьмите сумму вдоль оси = 1, чтобы получить количество. ‘
3. @windwalker вы можете представить основные диагональные значения в маске в результате сравнения текущего datetime в
appt_start
с текущим datetime вappt_end
и все предшествующие логические значения в результате сравнения текущего datetime вappt_start
со всеми предыдущими значениями datetimeappt_end
в. Надеюсь, это делает его более понятным.