python - 熊猫:在列高于或等于 0 时复制数据框条目
问题描述
我有一个包含医院患者临床读数的数据框,例如类似的数据框可能如下所示
heartrate pid time
0 67 151 0.0
1 75 151 1.2
2 78 151 2.5
3 99 186 0.0
实际上还有更多列,但我将只保留这 3 个以使示例更简洁。
我想“扩展”数据集。简而言之,我希望能够给出一个论点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 个多小时。
有没有办法使用熊猫操作来加快速度?我环顾四周,但到目前为止,我还没有设法用高级熊猫功能重现此功能
解决方案
最终使用了 groupby 函数并在没有更多时间可用时中断,并创建了一个“索引”列,我在最后与“pid”列合并。
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']
推荐阅读
- python - 从 AbstractBaseUser 中省略 is_staff 的后果是什么?
- json - Python Lambda 操作 CSV 文件一次但不是第二次
- soap - 对具有特定价格水平的商品进行 ItemSearchBasic?
- c# - eBay Trading API 需要 GetOrders 方法所需的参数,但要处理,有些需要无价值。空,不接受
- cloud - 无法从 Data Fusion 连接 Cloud SQL PostgreSQL
- facebook - 如何授予合作伙伴商务管理器中的管理员系统用户对客户业务的权限?
- windows - Cygwin bash 和 vue-cli-service 服务未运行 Web 开发服务器
- apache-spark - Pyspark - 查找在过去项目中一起工作的员工
- c++ - 带 USB 集线器的 C++ 串行端口
- kubernetes - 是否可以将 pod 配置为优先使用“hostNetwork”但仍引用内部服务端点?