如何编写按ID清理Pandas DataFrame指定行的函数
Pandas DataFrame 数据清理问题
原始数据集
| id | col1 | col2 | value1 | value2 | value3 |
|---|---|---|---|---|---|
| 1 | 123456 | 1234ABC | 1 | 2 | nan |
| 1 | 123456 | 1234567 | 1 | 2 | nan |
| 1 | 124567 | 1234568 | 1 | 2 | nan |
| 1 | 124567 | 2345678 | nan | 2 | nan |
| 2 | 123456 | 1234564 | nan | 2 | nan |
| 2 | 123456 | 2132534 | nan | 2 | nan |
| 2 | 543210 | 10580701 | nan | 2 | nan |
数据清理规则
针对每个唯一id执行以下逻辑:
- 若
col1为6位编码且col2包含字母数字组合:- 保留该行
- 若
col1为6位编码且col2非字母数字组合:- 保留该
col1编码对应的第一行
- 保留该
清理后期望结果
| id | col1 | col2 | value1 | value2 | value3 |
|---|---|---|---|---|---|
| 1 | 123456 | 1234ABC | 1 | 2 | nan |
| 1 | 123456 | 1234567 | 1 | 2 | nan |
| 1 | 124567 | 2345678 | nan | 2 | nan |
| 2 | 123456 | 1234564 | nan | 2 | nan |
| 2 | 543210 | 10580701 | nan | 2 | nan |
最初尝试的代码
def process_df(df): # Sort the dataframe by column 1 and column 2 df = df.sort_values(by=['col1', 'col2']) # Create a new column that indicates whether a row has a letter in column 2 df['has_letter'] = df['col2'].str.contains('[a-zA-Z]') # Group the dataframe by column 1 and apply the following function to each group def group_func(group): # If there are any rows with a letter in column 2, keep all of them if group['has_letter'].any(): return group # If there are no rows with a letter in column 2, keep the first row else: return group.iloc[0:1] df = df.groupby('col1').apply(group_func) # Drop the has_letter column df = df.drop(columns=['has_letter']) df=df.reset_index(drop=True) return df
问题分析
上述代码无法满足需求,因为不同id下可能存在相同的col1编码,代码仅按col1分组会导致跨id的同编码数据被错误合并处理,未实现按每个id单独处理的要求。
修改后的解决方案
将分组逻辑改为同时按id和col1分组,修改后的核心代码如下:
df = df.groupby(['id', 'col1']).apply(group_func)
修改后,分组会在每个id内部对不同的col1编码独立处理,完全符合数据清理规则的要求。
内容的提问来源于stack exchange,提问作者Lurri
相关产品推荐
相关产品推荐

