python - 动态构建索引以对 pandas 中的记录进行分类
问题描述
我正在尝试编写一个简单的记录分类器。我想添加一个其值对记录进行分类的列。我想将我的分类规则编入 yaml 或类似文件以进行维护。
我正在使用 Pandas,因为这似乎是使用 python 中的 csv 记录执行此操作的最佳方法。我愿意接受其他建议。我是 pandas 的新手,我的 python 技能被礼貌地描述为“为什么这看起来像 perl?”
我得到了一个数据框(trans),我想按如下方式应用我的规则:
trans['class'][(trans['foo'] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I))] = 'Record Type 1'
这以交互方式工作。我希望能够"(trans['foo'] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I))"
从我的 yaml 文件中的每个规则动态生成分类索引。我已经成功构建了字符串,这样我就有了类似的东西:
slice = "(trans['foo'] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I))"
trans['class'][slice] = 'Record Type 1'
这行不通。我应该怎么做?
解决方案
需要注意的几点:
- 引号表示 Python 中的字符串。不要使用它们来围绕布尔掩码的计算。
- 不要使用链式索引。在文档中明确不鼓励这样做,并且可能会导致意外的副作用,或者对于您是在修改视图还是副本的歧义。你可以
pd.DataFrame.loc
改用。 pd.Series.str.contains
已经支持正则表达式并默认为regex=True
,您不需要使用该re
模块。
为了便于阅读,您可以拆分和组合掩码。这是一个例子:
m1 = trans['foo'] > 5
m2 = trans['bar'].str.contains('baz|one|two', case=False)
trans.loc[m1 & m2, 'class'] = 'Record Type 1'
通常昂贵的部分,即 的计算m2
,可以通过使用专业算法进行优化,有关详细信息,请参阅此答案。