我有一份研究中受试者的纵向数据dataframe
。每个受试者在不同的时间点重复观察Wave
。一个数据点condition_A
表示为具有可能值的字符串,(normal, MCI, dementia)
其中所有受试者都在第 1 波condition_A = normal
。一些科目在不同的时间点继续发展condition_A = dementia
或condition_A = MCI
。其他科目在所有时间点condition_A = normal
。
我正在尝试找到一种方法,从condition_A
首先等于dementia
和任何未来波的时间点开始condition_A = dementia
对象中排除数据,同时保留任何先前的数据。
数据框设置如下:
>>> index = pd.MultiIndex.from_arrays([[1,1,1,2,2,2,3,3,3,4,4,4],[1,2,3]*4], names = ('SubjectID', 'Wave'))
>>> df = pd.DataFrame({"condition_A":['normal', 'normal', 'normal', 'normal', 'normal', 'dementia', 'normal', 'MCI', 'dementia', 'normal', 'dementia', 'dementia']}, index=index)
>>> df
condition_A
SubjectID Wave
1 1 normal
2 normal
3 normal
2 1 normal
2 normal
3 dementia
3 1 normal
2 MCI
3 dementia
4 1 normal
2 dementia
3 dementia
我想要的所需输出是:
condition_A
SubjectID Wave
1 1 normal
2 normal
3 normal
2 1 normal
2 normal
3 1 normal
2 MCI
4 1 normal
我尝试的一种方法是使用外部Series
对象来存储每个主题的包含/排除状态,然后在每行上使用apply
:
>>> df['condition_A_exclude'] = False
>>> subject_list = pd.Series(False, index=index.levels[0])
Int64Index([1, 2, 3], dtype='int64', name='SubjectID')
>>> def determine_condition_A(row):
... index = row['SubjectID']
... if subject_list.loc[index]:
... row['condition_A_exclude'] = True
... elif row['condition_A']=='dementia':
... subject_list.loc[index] = True
... row['condition_A_exclude'] = True
... return row
>>> df.apply(determine_condition_A, axis = 'columns')
此方法有效,但它依赖于外部系列。我想知道是否有办法做到这一点?
要排除所有数据(真或假),只要有 True,就可以使用groupby
+cummax
来计算掩码:
mask = df.groupby(level='SubjectID')['condition_A'].cummax()
# updated example with "dementia"
mask = df['condition_A'].eq('dementia').groupby(level='SubjectID').cummax()
df.loc[~mask]
输出:
condition_A
SubjectID Wave
1 1 False
2 1 False
2 False
3 1 False
2 False
3 False