Pandas新手求教:对比两DataFrame列并生成布尔标识列
简便实现跨DataFrame品牌信号区间匹配的方法
Hey there! 作为Pandas初学者,这种跨DataFrame的分组区间匹配需求其实有挺简洁的实现思路,我给你分享两种实用方法,你可以根据自己的场景选择:
方法一:合并后用自定义函数判断(逻辑直观,适合入门)
这种方法不需要复杂的数据结构转换,直接把两个DataFrame按Brand合并后,用自定义函数逐行判断信号所属区间,非常容易理解。
步骤示例:
- 首先准备你的数据(示例结构):
import pandas as pd # 示例df1 df1 = pd.DataFrame({ "Brand": ["A", "B"], "Signal_range": [ {"Weak": [0, 30], "Average": [30, 70], "Strong": [70, 100]}, {"Weak": [0, 25], "Average": [25, 75], "Strong": [75, 100]} ] }) # 示例df2 df2 = pd.DataFrame({ "order": [1, 2, 3], "Brand": ["A", "A", "B"], "signal": [25, 50, 80] })
- 合并两个DataFrame,保留品牌对应的信号区间:
merged_df = df2.merge(df1[["Brand", "Signal_range"]], on="Brand", how="left")
- 定义判断函数,生成布尔标识列:
def judge_signal_interval(row): range_dict = row["Signal_range"] sig_val = row["signal"] # 根据区间规则判断(这里假设区间左闭右开,可根据实际调整) weak_flag = range_dict["Weak"][0] <= sig_val < range_dict["Weak"][1] average_flag = range_dict["Average"][0] <= sig_val < range_dict["Average"][1] strong_flag = range_dict["Strong"][0] <= sig_val < range_dict["Strong"][1] return pd.Series([weak_flag, average_flag, strong_flag], index=["weak_ind", "Average_ind", "Strong_ind"]) # 应用函数生成标识列 merged_df[["weak_ind", "Average_ind", "Strong_ind"]] = merged_df.apply(judge_signal_interval, axis=1) # 可选:删除临时的Signal_range列 merged_df = merged_df.drop("Signal_range", axis=1)
执行后得到的结果就和你预期的示例一致啦:
order Brand signal weak_ind Average_ind Strong_ind 0 1 A 25 True False False 1 2 A 50 False True False 2 3 B 80 False False True
方法二:先展开区间列再用between(性能更优,适合大数据集)
如果你的数据量较大,apply逐行处理的性能会稍弱,这时可以先把df1的嵌套字典展开为区间上下限列,再用Pandas的between方法批量判断,速度更快。
步骤示例:
- 展开df1的Signal_range为区间上下限列:
# 把嵌套字典展开为多级索引列 df1_expanded = df1["Signal_range"].apply(pd.Series).applymap(lambda x: pd.Series(x, index=["low", "high"])) df1_expanded.columns = pd.MultiIndex.from_product([["Weak", "Average", "Strong"], ["low", "high"]]) # 和原Brand列合并,得到处理后的df1 df1_processed = pd.concat([df1[["Brand"]], df1_expanded], axis=1)
- 合并df2和处理后的df1:
merged_df = df2.merge(df1_processed, on="Brand", how="left")
- 用
between批量生成布尔列:
merged_df["weak_ind"] = merged_df["signal"].between(merged_df["Weak", "low"], merged_df["Weak", "high"], inclusive="left") merged_df["Average_ind"] = merged_df["signal"].between(merged_df["Average", "low"], merged_df["Average", "high"], inclusive="left") merged_df["Strong_ind"] = merged_df["signal"].between(merged_df["Strong", "low"], merged_df["Strong", "high"], inclusive="left") # 可选:删除多余的区间列 merged_df = merged_df.drop([("Weak","low"), ("Weak","high"), ("Average","low"), ("Average","high"), ("Strong","low"), ("Strong","high")], axis=1)
这个方法利用了Pandas的向量化操作,比逐行apply效率高很多,适合处理大规模数据。
注意事项
- 如果你的信号区间是闭区间(比如包含上限值),可以调整
between的inclusive参数为"both",或者在自定义函数里把<改成<=。 - 如果df2里有df1不存在的Brand,
merge时用how="left"会保留这些行,对应的标识列会是NaN,你可以根据需求用fillna(False)处理。
内容的提问来源于stack exchange,提问作者JackJack
相关产品推荐
相关产品推荐

