动态构建索引以对 pandas 中的记录进行分类
Posted
技术标签:
【中文标题】动态构建索引以对 pandas 中的记录进行分类【英文标题】:Dynamically building indexes to classify records in pandas 【发布时间】:2019-03-12 21:02:55 【问题描述】:我正在尝试编写一个简单的记录分类器。我想添加一个其值对记录进行分类的列。我想将我的分类规则编入 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'
这是交互式的。我希望能够从我的 yaml 文件中的每个规则动态生成分类索引"(trans['foo'] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I))"
。我已经成功构建了字符串,这样我就有了这样的东西:
slice = "(trans['foo'] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I))"
trans['class'][slice] = 'Record Type 1'
这不起作用。我应该怎么做?
【问题讨论】:
【参考方案1】:我认为您不应该将条件放在引号内。所以应该是
slice = (trans[`foo`] > 5) & (trans['bar'].str.contains(re.compile('baz|one|two', re.I)))
trans['class'][slice] = "Record Type 1"
【讨论】:
如果表达式以字符串s
的形式出现,您可以使用slice = eval(s)
。 @jpp 的笔记都很棒,值得考虑,尤其是第二名。
我在代码中构建了自己的字符串,缺少的是 eval。我误解了切片在链式逻辑中的含义。我在文档中简要阅读了链式对话,并决定它不适用于我的情况,因为我不担心覆盖数据框。也就是说,既然我知道如何避免它,我打算避免它。【参考方案2】:
需要注意的几点:
-
引号表示 Python 中的字符串。不要使用它们来包围布尔掩码的计算。
不要使用链式索引。它是文档中的explicitly discouraged,它可能会导致意外的副作用,或者是在修改视图还是副本时产生歧义。您可以改用
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
的计算,可以通过专业算法进行优化,详情请参阅this answer。
【讨论】:
您将如何处理在运行时之前存在未知数量的条件的情况?即可能需要 m1、m1&m2 或 m1&m2&m3 等。你能像 m = m & new_condition 这样迭代吗? 当然,您可以通过这种方式链接任意数量的布尔系列,例如m = m1 & m2 & (m3 | m4) & (m5 | m6)
,然后计算m = m & m7
等。
谢谢您-我点击了并忘记了检查-doh!这看起来非常有帮助。谢谢。以上是关于动态构建索引以对 pandas 中的记录进行分类的主要内容,如果未能解决你的问题,请参考以下文章