我有一个包含医院患者临床读数的数据框,例如类似的数据框可能看起来像这样
heartrate pid time
0 67 151 0.0
1 75 151 1.2
2 78 151 2.5
3 99 186 0.0
实际上还有更多列,但我会保留这些列以使示例更简洁。
我想“扩展”数据集。简而言之,我希望能够给出一个参数n_times_back
和另一个参数interval
。
对于每次对应for i in range (n_times_back + 1)
的迭代,我们执行以下操作:
创建一个新的,唯一的pid [OLD ID | i]
(虽然只要新的
pid
对于每个重复的条目都是唯一的,确切的名称不是
对我来说非常重要,所以如果它成功的话,请随意改变它
更容易)
对于每位患者(pid),请删除time
列的行
超过final time of that patient - i * interval
。对于
示例i * interval = 2.0
以及与pid
相关联的时间
是[0, 0.5, 1.5, 2.8]
,新时间为[0, 0.5]
,final
time - 2.0 = 0.8
迭代
因为我意识到在文本上解释这个有点乱,所以这是一个例子。
使用上面的数据集,如果我们允许n_times_back = 1
和interval=1
,那么我们就会
heartrate pid time
0 67 15100 0.0
1 75 15100 1.2
2 78 15100 2.5
3 67 15101 0.0
4 75 15101 1.2
5 99 18600 0.0
对于n_times_back = 2
,结果将是
heartrate pid time
0 67 15100 0.0
1 75 15100 1.2
2 78 15100 2.5
3 67 15101 0.0
4 75 15101 1.2
5 67 15102 0.0
6 99 18600 0.0
n_times_back = 3
及以上会导致与n_times_back = 2
相同的结果,因为没有患者数据低于该时间点
我已为此编写代码。
def expand_df(df, n_times_back, interval):
for curr_patient in df['pid'].unique():
patient_data = df[df['pid'] == curr_patient]
final_time = patient_data['time'].max()
for i in range(n_times_back + 1):
new_data = patient_data[patient_data['time'] <= final_time - i * interval]
new_data['pid'] = patient_data['pid'].astype(str) + str(i).zfill(2)
new_data['pid'] = new_data['pid'].astype(int)
#check if there is any time index left, if not don't add useless entry to dataframe
if(new_data['time'].count()>0):
df = df.append(new_data)
df = df[df['pid'] != curr_patient] # remove original patient data, now duplicate
df.reset_index(inplace = True, drop = True)
return df
就功能而言,此代码按预期工作。但是,它很慢。我正在使用30,000名患者的数据框,代码已经运行了2个多小时。
有没有办法使用pandas操作加快速度?我环顾四周,但到目前为止,我还没有设法用高级熊猫功能重现这个功能
答案 0 :(得分:1)
最终使用groupby函数,并在没有更多时间可用时中断,以及创建&#34;索引&#34;我与&#34; pid&#34;合并的列最后一栏。
def expand_df(group, n_times, interval):
df = pd.DataFrame()
final_time = group['time'].max()
for i in range(n_times + 1):
new_data = group[group['time'] <= final_time - i * interval]
new_data['iteration'] = str(i).zfill(2)
#check if there is any time index left, if not don't add useless entry to dataframe
if(new_data['time'].count()>0):
df = df.append(new_data)
else:
break
return df
new_df = df.groupby('pid').apply(lambda x : expand_df(x, n_times_back, interval))
new_df = new_df.reset_index(drop=True)
new_df['pid'] = new_df['pid'].map(str) + new_df['iteration']