首页 > 解决方案 > 动态构建索引以对 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'

这行不通。我应该怎么做?

标签: pythonstringpandasindexingseries

解决方案


需要注意的几点:

  1. 引号表示 Python 中的字符串。不要使用它们来围绕布尔掩码的计算。
  2. 不要使用链式索引。在文档中明确不鼓励这样做,并且可能会导致意外的副作用,或者对于您是在修改视图还是副本的歧义。你可以pd.DataFrame.loc改用。
  3. 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,可以通过使用专业算法进行优化,有关详细信息,请参阅此答案


推荐阅读