TL; DR
# (see is_desc function definition below)
df['is_desc'] = df.groupby('PationtID').PSA.transform(is_desc)
df[df['is_desc']]
Объяснение
Давайте использовать очень простой набор данных:
df = pd.DataFrame({'id': [1,2,1,3,3,1], 'res': [3,1,2,1,5,1]})
Содержит только идентификатор и один столбец значений (и имеет индекс, автоматически назначаемый из панд).
Так что, если вы просто хотите получить список всех идентификаторов, значения которых являются убывающими, мы можем сгруппировать значения по идентификатору, затем проверить, являются ли значения в группе убывающими, а затем отфильтровать список только идентификаторов с убывающими значениями. .
Итак, сначала давайте определим функцию, которая проверяет, уменьшаются ли значения:
def is_desc(d):
first = True
for i in d:
if first:
first = False
else:
if i >= last:
return False
last = i
return True
(да, возможно, это можно было бы сделать более элегантно, для лучшей реализации вы можете выполнить поиск в Интернете)
теперь мы группируем по id :
gb = df.groupby('id')
и применяют функцию :
x = gb.res.apply(is_desc)
x
теперь содержит это Series
:
id
1 True
2 True
3 False
dtype: bool
так что теперь, если вы хотите отфильтровать это, вы можете просто сделать это:
x[x].index
который вы, конечно, можете преобразовать в обычный список следующим образом:
list(x[x].index)
, который даст вам список всех идентификаторов, значения которых убывают. в этом случае:
[1, 2]
Но если вы хотите также иметь все исходные данные для всех выбранных идентификаторов, сделайте это так:
df['is_desc'] = gb.res.transform(is_des)
, поэтому теперь df имеет все исходные данные, которые он имел в начале, плюс столбец, который сообщает для каждой строки, если значения его id убывают:
id res is_desc
0 1 3 True
1 2 1 True
2 1 2 True
3 3 1 False
4 3 5 False
5 1 1 True
Теперь вы можете очень легко отфильтровать это так:
df[df['is_desc']]
что:
id res is_desc
0 1 3 True
1 2 1 True
2 1 2 True
5 1 1 True