Как сгруппировать по одному столбцу и найти второе вхождение значений, превышающих пороговое значение

Вопрос или проблема

Проблема

У меня есть dataframe pandas, который содержит серии данных о людях, номер недели, когда произошел визит, и их систолическое и диастолическое артериальное давление.

ID   Weeks   Systolic     Diastolic
1    9       140          90
1    15      155          97
2    7       140          90
2    8       121          75 
2    9       161          93
3    2       160          92
3    20      139          87
3    21      140          95
3    22      145          96
4    5       155          90
4    3       150          97

Что я хочу сделать, так это сгруппировать каждого пациента по ID, отметить, когда у кого-то артериальное давление превысило 140/90, и выяснить, когда артериальное давление пациента превысило это значение во второй раз.

Например, в таблице выше у пациента 3 артериальное давление превышает 140/90 на неделях 2, 21 и 22, поэтому второй случай будет на неделе 21. В результате dataframe будет выглядеть следующим образом:

ID     Неделя второго пика
1      15
2      9
3      21
4      5

Что я пробовал

Я могу создать индикаторную переменную, которая показывает, где в dataframe артериальное давление превышает эти значения:

df['High'] = np.where((df['Systolic'] >= 140) & (df['Diastolic'] >= 90) , 1, 0)

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

Я нашел одно решение благодаря этой теме на SO. В итоге я сделал следующее:

Сначала я создал индикаторную переменную, описанную в вопросе:

df['High'] = np.where((df['Systolic'] >= 140) & (df['Diastolic'] >= 90) , 1, 0)

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

df['Prev_highBP'] = df.groupby(['ID'])['High'].cumsum().astype(int)

Затем я отфильтровал людей с высоким давлением, сгруппировав по ID, и создал новую переменную для хранения второй наименьшей недели в этой группе.

grouped = df.loc[testPre['High']==1].groupby(['ID'])['Week']
df['second_spike'] = grouped.transform(lambda x: x.nsmallest(2).max())

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

df['second_spike'] = np.where((df['Prev_highBP'] != 2) , np.NaN, df['second_spike'])

Тогда я могу получить нужный dataframe, просто удалив дубликаты:

secondSpike = df.drop_duplicates(subset=['ID'], keep='last')

Скорее всего, есть более чистый или эффективный способ сделать это, но на данный момент это кажется рабочим.

Ответ или решение

Как сгруппировать по одному столбцу и найти второе появление значений, превышающих заданный порог

Работа с данными о здоровье — важная задача, требующая внимательного анализа. В вашем случае требуется обработать данные о пациентах, фиксируя их артериальное давление. Рассмотрим, как сгруппировать данные по идентификатору пациента и определить вторую дату, когда артериальное давление превышало указанный порог (140/90 для систолического и диастолического давления).

1. Подготовка данных

Для начала, необходимо импортировать библиотеки и создать DataFrame с вашими данными:

import pandas as pd
import numpy as np

data = {
    'ID': [1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4],
    'Weeks': [9, 15, 7, 8, 9, 2, 20, 21, 22, 5, 3],
    'Systolic': [140, 155, 140, 121, 161, 160, 139, 140, 145, 155, 150],
    'Diastolic': [90, 97, 90, 75, 93, 92, 87, 95, 96, 90, 97]
}

df = pd.DataFrame(data)

2. Создание индикаторной переменной

Во-первых, мы создаем индикаторную переменную, чтобы пометить, когда артериальное давление превышает заданный порог:

df['High'] = np.where((df['Systolic'] >= 140) & (df['Diastolic'] >= 90), 1, 0)

3. Подсчет спикеров давления

Далее мы используем функцию кумулятивной суммы для подсчета количества раз, когда у пациента произошло повышение давления:

df['Prev_highBP'] = df.groupby('ID')['High'].cumsum().astype(int)

4. Группировка и нахождение второго появления

Теперь мы можем сгруппировать данные по ID и найти второе появление высокой артериальной нагрузки:

grouped = df[df['High'] == 1].groupby('ID')['Weeks']
df['second_spike'] = grouped.transform(lambda x: x.nsmallest(2).max())

5. Обработка случаев с одним всплеском

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

df['second_spike'] = np.where(df['Prev_highBP'] != 2, np.NaN, df['second_spike'])

6. Создание итогового DataFrame

Наконец, мы можем извлечь итоговый DataFrame, в котором будет только информация о втором всплеске давления для каждого пациента:

secondSpike = df.drop_duplicates(subset=['ID'], keep='last')[['ID', 'second_spike']]
secondSpike.rename(columns={'second_spike': 'Week of Second Spike'}, inplace=True)

Итоговый результат

В результате вы получите DataFrame, представляющий собой ID пациента и неделю, когда произошло второе повышение давления:

   ID  Week of Second Spike
0  1                  15.0
1  2                  9.0
2  3                  21.0
3  4                   5.0

Заключение

Эта процедура позволяет вам эффективно анализировать данные о здоровье пациентов и выявлять значимые временные моменты, такие как второе внезапное повышение артериального давления. Используя комбинацию функций Pandas, вы можете гибко настраивать анализ для получения уникальной аналитики по каждому пациенту.

Оцените материал
Добавить комментарий

Капча загружается...