如何在Pandas中比较值域不同的category类型列的相等性
Pandas中无需转换类型即可比较值域不同的Category列的方法
处理大型数据集时,将Object列转为Category类型是常用的内存优化手段,但当需要用pd.query()比较值域不同的Category列时,直接比较会触发报错,而全局转为Object类型又会导致内存占用剧增。以下是几种无需全量转换类型的解决方法:
方法1:统一Category列的类别集合
将两个Category列的类别合并为同一个集合,让它们共享相同的类别体系,这样就能直接进行相等性比较,同时保留Category的内存优势:
import pandas as pd df = pd.DataFrame({"c1":["a","b","c","d"], "c2":["d","e","f","d"]}) # 合并两列的所有唯一类别 combined_categories = pd.unique(df[["c1", "c2"]].values.ravel('K')) # 重新设置Category类型,使用合并后的类别 df["c1"] = pd.Categorical(df["c1"], categories=combined_categories) df["c2"] = pd.Categorical(df["c2"], categories=combined_categories) # 现在可直接用query比较 result = df.query("c1 == c2") print(result)
输出:
c1 c2 3 d d
方法2:在query中基于编码+共类别过滤比较
不修改原列的Category类型,先获取两列共有的类别,再通过cat.codes比较编码,同时过滤掉仅存在于单一列的类别:
import pandas as pd df = pd.DataFrame({"c1":["a","b","c","d"], "c2":["d","e","f","d"]}) df["c1"] = df["c1"].astype("category") df["c2"] = df["c2"].astype("category") # 获取两列共有的类别 common_cats = set(df["c1"].cat.categories) & set(df["c2"].cat.categories) # 先过滤出共类别内的行,再比较编码 result = df.query("c1 in @common_cats and c2 in @common_cats and c1.cat.codes == c2.cat.codes") print(result)
输出:
c1 c2 3 d d
方法3:利用cat.str属性进行字符串比较
通过cat.str获取Category列的字符串表示进行比较,这种方式不会将整个列转为Object类型,内存占用远低于全量转换:
import pandas as pd df = pd.DataFrame({"c1":["a","b","c","d"], "c2":["d","e","f","d"]}) df["c1"] = df["c1"].astype("category") df["c2"] = df["c2"].astype("category") # 使用cat.str进行字符串比较 result = df.query("c1.cat.str == c2.cat.str") print(result)
输出:
c1 c2 3 d d
以上三种方法都能在保持Category内存优势的前提下,解决值域不同的Category列在pd.query()中的比较问题,避免MemoryError的发生。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

