Количество значений в столбце x больше, чем одно значение в столбце y — Python

#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 со всеми предыдущими значениями datetime appt_end в. Надеюсь, это делает его более понятным.