如何结合对应位置条件同时遍历两个DataFrame并筛选数据?
筛选符合条件的DataFrame行
我有两个DataFrame,需求是:遍历第一个DataFrame(df1),当其中元素满足以'XY'开头的条件时,检查第二个DataFrame(df2)对应行列位置的日期是否早于'2003-01-01';最终保留df1中所有以'XY'开头的元素对应的df2日期都不早于2003-01-01的行。
df1结构
| id | 1 | 2 | 3 |
|---|---|---|---|
| 0 | XY00 | AB80 | XY01 |
| 1 | FY34 | XY60 | XY91 |
| 2 | AB46 | AC40 | NY23 |
| 3 | XY70 | AB23 | DG60 |
df2结构(与df1行索引对应,列名不同但位置匹配)
| id | e1 | e2 | e3 |
|---|---|---|---|
| 0 | 2003-12-09 | 2005-01-01 | 2006-12-14 |
| 1 | 2004-11-09 | 2002-01-01 | 1999-07-10 |
| 2 | 2012-02-13 | 2011-08-22 | 2003-03-16 |
| 3 | 2003-01-17 | 2005-01-01 | 2017-09-30 |
理想输出
| id | 1 | 2 | 3 |
|---|---|---|---|
| 0 | XY00 | AB80 | XY01 |
| 3 | XY70 | AB23 | DG60 |
我的错误代码(输出空DataFrame)
new_df = pd.DataFrame(data = None, columns = df1.columns) for ind, row in df1.iterrows(): if ((ind,row) == ("XY00")): for ind2, row2 in df2.iterrows(): if((ind2,row2) >= ("2003-01-01")): new_df = new_df.append(row)
错误原因分析
- 判断逻辑完全错误:
(ind,row) == ("XY00")中,ind是行索引(如0、1),row是整行数据的Series,不可能等于单个字符串"XY00",根本无法触发后续逻辑。 - 不必要的嵌套遍历:df1和df2行索引一一对应,无需重新遍历df2所有行,直接通过索引取对应行即可。
- 条件与需求相悖:需求是检查日期是否早于2003-01-01,代码中写的是
>=,且未将日期转为datetime类型,虽然字符串格式可比较,但不够严谨。 - 未处理列对应关系:df1的列是
1、2、3,df2的是e1、e2、e3,代码未建立对应映射,无法匹配正确位置。
正确解决方案
方法1:向量化操作(推荐,pandas最优实践)
利用pandas的向量化运算,避免低效循环:
import pandas as pd # 将df2的日期列转为datetime类型 df2 = df2.apply(pd.to_datetime) # 定义目标日期 target_date = pd.to_datetime('2003-01-01') # 建立列映射关系 col_map = {'1': 'e1', '2': 'e2', '3': 'e3'} # 生成布尔掩码:标记每行是否存在「XY开头元素且对应日期早于目标日期」的情况 mask = ~( (df1[col_map.keys()].apply(lambda x: x.str.startswith('XY'))) & (df2[col_map.values()] < target_date) ).any(axis=1) # 筛选符合条件的行 new_df = df1[mask] print(new_df)
方法2:修正后的循环方法(贴合原思路)
如果坚持用循环,修正逻辑如下:
import pandas as pd new_df = pd.DataFrame(columns=df1.columns) target_date = pd.to_datetime('2003-01-01') # 转换df2日期类型 df2 = df2.apply(pd.to_datetime) # 列对应映射 col_map = {'1': 'e1', '2': 'e2', '3': 'e3'} for ind, row in df1.iterrows(): keep_row = True # 获取df2对应行数据 df2_row = df2.loc[ind] # 遍历需要检查的列 for df1_col, df2_col in col_map.items(): val = row[df1_col] if val.startswith('XY'): # 检查对应日期是否早于目标日期 if df2_row[df2_col] < target_date: keep_row = False break # 只要有一个不符合,直接终止当前行检查 if keep_row: # 将符合条件的行添加到新DataFrame new_df = pd.concat([new_df, row.to_frame().T], ignore_index=True) print(new_df)
内容的提问来源于stack exchange,提问作者maissam
相关产品推荐
相关产品推荐

