【发布时间】:2021-10-05 07:10:28
【问题描述】:
我有一个由医疗数据组成的 DataFrame,其中的列是 [“Patient_ID”、“Code”、“Data”],其中“Code”仅代表患者“Patient_ID”在“日期”上进行的一些医疗交互。任何患者通常会有不止一排,因为他们有不止一个交互。我想对这些数据应用两种类型的过滤。
- 删除所有
min_len互动次数少于一些的患者 - 对每位患者应用一个长度为
T天的半重叠滑动窗口。在每个窗口内只保留第一个重复的代码,然后在窗口内打乱代码
所以我需要修改整个数据框的子集,但修改涉及更改子集的大小。我将这两个实现为更大管道的一部分,但是就时间而言,它们是一个重要的瓶颈。我想知道是否有更有效的方法来实现同样的事情,因为我真的只是把有用的东西放在一起,而且我对 pandas 操作的效率不太熟悉。以下是我目前拥有它们的方式:
def Filter_by_length(df, min_len = 1):
print("Filtering short sequences...")
df = df.sort_values(axis = 0, by = ['ID', 'DATE']).copy(deep = True)
new_df = []
for sub_df in tqdm((df[df.ID == sub] for sub in df.ID.unique()), total = len(df.ID.unique()), miniters = 1):
if len(sub_df) >= min_len:
new_df.append(sub_df.copy(deep = True))
if len(new_df) != 0:
df = pd.concat(new_df, sort = False)
else:
df = pd.DataFrame({})
print("Done")
return df
def shuffle_col(df, col):
df[col] = np.random.permutation(df[col])
return df
def Filter_by_redundancy(df, T, min_len = 1):
print("Filtering redundant concepts and short sequences...")
df = df.sort_values(axis = 0, by = ['ID', 'DATE']).copy(deep = True)
new_df = []
for sub_df in tqdm((df[df.ID == sub] for sub in df.ID.unique()), total = len(df.ID.unique()), miniters = 1):
start_date = sub_df.DATE.min()
end_date = sub_df.DATE.max()
next_date = start_date + dt.timedelta(days = T)
while start_date <= end_date:
sub_df = pd.concat([sub_df[sub_df.DATE < start_date],\
shuffle_col(sub_df[(sub_df.DATE <= next_date) & (sub_df.DATE >= start_date)]\
.drop_duplicates(subset = ['CODE']), "CODE"),\
sub_df[sub_df.DATE > next_date]], sort = False )
start_date += dt.timedelta(days = int(T/2))
next_date += dt.timedelta(days = int(T/2))
if len(sub_df) >= min_len:
new_df.append(sub_df.copy(deep = True))
if len(new_df) != 0:
df = pd.concat(new_df, sort = False)
else:
df = pd.DataFrame({})
print("Done")
return df
如您所见,在第二种情况下,我实际上同时应用了两个过滤器,因为可以选择同时应用这两个过滤器或单独应用一个过滤器很重要,但我对可以进行的任何性能改进感兴趣一个或两个。
【问题讨论】:
-
通过
df.groupby('id').size()获取组长度,然后删除任何长度不足的ID。我不确定您的其他部分完全是做什么的,但您也可以随时将for sub_df in [df[df['id'] == i] for i in df['id'].unique()]替换为for id, sub_df in df.groupby('id') -
这种方法的长度要快得多,谢谢。
标签: pandas dataframe filtering data-manipulation