pandas 数据帧的一个子集的一个子集的更新值对于大型数据集来说太慢了
Updating values for a subset of a subset of a pandas dataframe too slow for large data set
问题陈述:我正在处理医院所有就诊的交易数据,我需要在每个患者的第一笔坏账交易之后删除每笔坏账交易。
我遇到的问题: 我的代码适用于小型数据集,但实际数据集约为 5GB 和 1300 万行。代码已经 运行 好几天了,仍然没有完成。作为背景,我的代码位于标准工作 PC 上的 Jupyter 笔记本 运行 中。
示例数据
import pandas as pd
df = pd.DataFrame({"PatientAccountNumber":[113,113,113,113,225,225,225,225,225,225,225],
"TransactionCode":['50','50','77','60','22','77','25','77','25','77','77'],
"Bucket":['Charity','Charity','Bad Debt','3rd Party','Self Pay','Bad Debt',
'Charity','Bad Debt','Charity','Bad Debt','Bad Debt']})
print(df)
示例数据框
PatientAccountNumber TransactionCode Bucket
0 113 50 Charity
1 113 50 Charity
2 113 77 Bad Debt
3 113 60 3rd Party
4 225 22 Self Pay
5 225 77 Bad Debt
6 225 25 Charity
7 225 77 Bad Debt
8 225 25 Charity
9 225 77 Bad Debt
10 225 77 Bad Debt
解决方案
for account in df['PatientAccountNumber'].unique():
mask = (df['PatientAccountNumber'] == account) & (df['Bucket'] == 'Bad Debt')
df.drop(df[mask].index[1:],inplace=True)
print(df)
期望的结果(每位患者最多应进行一次坏账交易)
PatientAccountNumber TransactionCode Bucket
0 113 50 Charity
1 113 50 Charity
2 113 77 Bad Debt
3 113 60 3rd Party
4 225 22 Self Pay
5 225 77 Bad Debt
6 225 25 Charity
8 225 25 Charity
备用解决方案
for account in df['PatientAccountNumber'].unique():
mask = (df['PatientAccountNumber'] == account) & (df['Bucket'] == 'Bad Debt')
mask = mask & (mask.cumsum() > 1)
df.loc[mask, 'Bucket'] = 'DELETE'
df = df[df['Bucket'] != 'DELETE]
尝试使用 Dask
我想也许 Dask 可以帮我解决问题,但我收到了以下错误代码:
- 在第一个解决方案上使用 Dask -“NotImplementedError:系列 getitem 仅支持具有匹配分区结构的其他系列对象”
- 在第二种解决方案中使用 Dask -“TypeError:‘_LocIndexer’对象不支持项目分配”
创建一个没有循环的布尔掩码:
mask = df[df['Bucket'].eq('Bad Debt')].duplicated('PatientAccountNumber')
df.drop(mask[mask].index, inplace=True)
>>> df
PatientAccountNumber TransactionCode Bucket
0 113 50 Charity
1 113 50 Charity
2 113 77 Bad Debt
3 113 60 3rd Party
4 225 22 Self Pay
5 225 77 Bad Debt
6 225 25 Charity
8 225 25 Charity
您可以在 accountNumber 和 Bucket 上使用 df.duplicated 并检查 Bucket 是否为坏帐来解决此问题:
df[~(df.duplicated(['PatientAccountNumber','Bucket']) & df['Bucket'].eq("Bad Debt"))]
PatientAccountNumber TransactionCode Bucket
0 113 50 Charity
1 113 50 Charity
2 113 77 Bad Debt
3 113 60 3rd Party
4 225 22 Self Pay
5 225 77 Bad Debt
6 225 25 Charity
8 225 25 Charity
问题陈述:我正在处理医院所有就诊的交易数据,我需要在每个患者的第一笔坏账交易之后删除每笔坏账交易。
我遇到的问题: 我的代码适用于小型数据集,但实际数据集约为 5GB 和 1300 万行。代码已经 运行 好几天了,仍然没有完成。作为背景,我的代码位于标准工作 PC 上的 Jupyter 笔记本 运行 中。
示例数据
import pandas as pd
df = pd.DataFrame({"PatientAccountNumber":[113,113,113,113,225,225,225,225,225,225,225],
"TransactionCode":['50','50','77','60','22','77','25','77','25','77','77'],
"Bucket":['Charity','Charity','Bad Debt','3rd Party','Self Pay','Bad Debt',
'Charity','Bad Debt','Charity','Bad Debt','Bad Debt']})
print(df)
示例数据框
PatientAccountNumber TransactionCode Bucket
0 113 50 Charity
1 113 50 Charity
2 113 77 Bad Debt
3 113 60 3rd Party
4 225 22 Self Pay
5 225 77 Bad Debt
6 225 25 Charity
7 225 77 Bad Debt
8 225 25 Charity
9 225 77 Bad Debt
10 225 77 Bad Debt
解决方案
for account in df['PatientAccountNumber'].unique():
mask = (df['PatientAccountNumber'] == account) & (df['Bucket'] == 'Bad Debt')
df.drop(df[mask].index[1:],inplace=True)
print(df)
期望的结果(每位患者最多应进行一次坏账交易)
PatientAccountNumber TransactionCode Bucket
0 113 50 Charity
1 113 50 Charity
2 113 77 Bad Debt
3 113 60 3rd Party
4 225 22 Self Pay
5 225 77 Bad Debt
6 225 25 Charity
8 225 25 Charity
备用解决方案
for account in df['PatientAccountNumber'].unique():
mask = (df['PatientAccountNumber'] == account) & (df['Bucket'] == 'Bad Debt')
mask = mask & (mask.cumsum() > 1)
df.loc[mask, 'Bucket'] = 'DELETE'
df = df[df['Bucket'] != 'DELETE]
尝试使用 Dask
我想也许 Dask 可以帮我解决问题,但我收到了以下错误代码:
- 在第一个解决方案上使用 Dask -“NotImplementedError:系列 getitem 仅支持具有匹配分区结构的其他系列对象”
- 在第二种解决方案中使用 Dask -“TypeError:‘_LocIndexer’对象不支持项目分配”
创建一个没有循环的布尔掩码:
mask = df[df['Bucket'].eq('Bad Debt')].duplicated('PatientAccountNumber')
df.drop(mask[mask].index, inplace=True)
>>> df
PatientAccountNumber TransactionCode Bucket
0 113 50 Charity
1 113 50 Charity
2 113 77 Bad Debt
3 113 60 3rd Party
4 225 22 Self Pay
5 225 77 Bad Debt
6 225 25 Charity
8 225 25 Charity
您可以在 accountNumber 和 Bucket 上使用 df.duplicated 并检查 Bucket 是否为坏帐来解决此问题:
df[~(df.duplicated(['PatientAccountNumber','Bucket']) & df['Bucket'].eq("Bad Debt"))]
PatientAccountNumber TransactionCode Bucket
0 113 50 Charity
1 113 50 Charity
2 113 77 Bad Debt
3 113 60 3rd Party
4 225 22 Self Pay
5 225 77 Bad Debt
6 225 25 Charity
8 225 25 Charity