You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过匹配Total_Area与Basement_Area最近值填充DataFrame字段

问题描述

我有两个DataFrame:
df1:

Year City     Address  Total_Area Basement_Area
1989 Ottawa   empty    280         130

另一个更大的df2需要通过Total_Area和Basement_Area匹配最近邻:
df2:

Year Address(with city in it) Total_Area Basement_Area
1989 123 Test Ottawa          279        120
1989 146 Test Ottawa          276        140
1989 156 Test Ottawa          283        134

期望结果是将df1的Address字段替换为匹配到的地址:

Year City     Address           Total_Area Basement_Area
1989 Ottawa   156 Test Ottawa   280         130

我尝试写了如下函数,但无法正确筛选并获取目标地址,求指导:

def filter_df(df,year,city,basement=0, floor_area=0, heated_floor_area=0,mp_storeys=0):
    if basement == 0:
        df = df[df[const.BASEMENT_COLUMN_df2_NAME].isnull()]
    else:
        df = df[(df[const.BASEMENT_COLUMN_df2_NAME]- floor_area).abs()< 10]
    


    filtered_df = df[(df[const.YEAR_COLUMN_df2_NAME] == year)]
    filtered_df = df[(df[const.ADDRESS_COLUMN_df2_NAME].str.contains(city))]
    filtered_df = df[(df[const.TOTAL_AREA_COLUMN_df2_NAME] - floor_area).abs()< 10]

    return filtered_df[0]

问题分析与修正

你的函数存在几个关键问题:

  • 筛选逻辑覆盖错误:每次赋值filtered_df = df[xxx]都会覆盖之前的筛选结果,而非叠加条件。比如先按年份筛选后,直接用原始df按地址包含城市筛选,之前的年份筛选就失效了。
  • 地下室面积匹配逻辑错误:else分支里用Basement_Area - floor_area计算差值,应该和传入的basement参数比较,而非floor_area。
  • 最近邻匹配缺失:当前代码只做了阈值内的筛选,没有在符合条件的结果里找到与df1数据最接近的行。
  • 结果取值错误:filtered_df[0]不是正确的取行方式,需用.iloc[0],且要先确保筛选后有结果。

下面是修正后的代码,实现基于Total_Area和Basement_Area的欧氏距离最近邻匹配:

import numpy as np

def filter_df(df, year, city, basement=0, floor_area=0, **kwargs):
    # 1. 基础筛选:年份匹配 + 地址包含城市
    filtered_df = df[
        (df[const.YEAR_COLUMN_df2_NAME] == year) &
        (df[const.ADDRESS_COLUMN_df2_NAME].str.contains(city, na=False))
    ]
    
    # 2. 地下室面积筛选:传入非0值时,保留差值在10以内的行
    if basement != 0:
        filtered_df = filtered_df[
            (filtered_df[const.BASEMENT_COLUMN_df2_NAME] - basement).abs() < 10
        ]
    
    # 3. 总面积筛选:保留差值在10以内的行
    filtered_df = filtered_df[
        (filtered_df[const.TOTAL_AREA_COLUMN_df2_NAME] - floor_area).abs() < 10
    ]
    
    # 4. 计算欧氏距离,找到最近邻
    if not filtered_df.empty:
        # 计算每行与目标值的距离
        filtered_df['distance'] = np.sqrt(
            (filtered_df[const.TOTAL_AREA_COLUMN_df2_NAME] - floor_area)**2 +
            (filtered_df[const.BASEMENT_COLUMN_df2_NAME] - basement)**2
        )
        # 取距离最小的行
        nearest_row = filtered_df.sort_values('distance').iloc[0]
        return nearest_row[const.ADDRESS_COLUMN_df2_NAME]
    else:
        # 无匹配结果时返回None或原地址
        return None

# 调用示例:遍历df1批量替换地址
df1['Address'] = df1.apply(
    lambda row: filter_df(
        df2,
        year=row['Year'],
        city=row['City'],
        basement=row['Basement_Area'],
        floor_area=row['Total_Area']
    ),
    axis=1
)

修正说明

  • 用&组合多个筛选条件,确保所有条件同时生效。
  • 地下室面积的差值计算改为与传入的basement参数对比,符合业务逻辑。
  • 加入欧氏距离计算,在符合阈值的结果中找到最接近的行,实现最近邻匹配。
  • 增加空值判断,避免筛选结果为空时报错。
  • 使用apply遍历df1每一行,批量完成地址替换。

内容的提问来源于stack exchange,提问作者Artur Akhmetgareev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 15:16:01