【问题标题】:py-datatable 'in' operator?py-datatable 'in' 运算符?
【发布时间】:2020-06-14 22:06:39
【问题描述】:

我无法使用预定义的项目列表执行标准in 操作。我想做这样的事情:

# Construct a simple example frame
from datatable import *
df = Frame(V1=['A','B','C','D'], V2=[1,2,3,4])

# Filter frame to a list of items (THIS DOES NOT WORK)
items = ['A','B']
df[f.V1 in items,:]

此示例导致错误:

TypeError: A boolean value cannot be used as a row selector

不幸的是,in 操作似乎没有内置对象。我想使用 R 语言原生的 %in% 运算符之类的东西。 有没有什么方法可以在 python 中实现这一点?

我可以通过使用多个“等于”运算符来采用这种方法,但是当您要考虑大量项目时,这很不方便:

df[(f.V1 == 'A') | (f.V1 == 'B'),:]

数据表 0.10.1
蟒蛇 3.6

【问题讨论】:

  • Pandas 对此有 Series.isin,但看起来 datatable 没有类似的东西。 (datatable 文档似乎非常稀少。)
  • @martineau:这个问题需要一个通过 LHS 广播的 in 版本,而 Python 的 in 无法做到这一点。

标签: python python-3.x datatable py-datatable


【解决方案1】:

你也可以试试这个:

首先将所有必要的包导入为,

import datatable as dt
from datatable import by,f,count
import functools
import operator

创建示例数据表:

DT = dt.Frame(V1=['A','B','C','D','E','B','A'], V2=[1,2,3,4,5,6,7])

列出要在观察中过滤的值,在你的情况下是

sel_obs = ['A','B']

现在使用 funtools 和 operator 模块创建过滤器表达式,

filter_rows = functools.reduce(operator.or_,(f.V1==obs for obs in sel_obs))

最后在数据表上应用上面创建的过滤器

DT[fil_rows,:]

它的输出为-

Out[6]: 
   | V1  V2
-- + --  --
 0 | A    1
 1 | B    2
 2 | B    6
 3 | A    7

[4 rows x 2 columns]

您可以随意使用运算符来执行不同类型的过滤。

@sammyweemy 的解决方案也应该有效。

【讨论】:

  • 很好玩 functools。下一步可能是速度测试,因为 pydatatable 的主要目标(我可能错了)是速度。
  • 随着行数的增加,这个速度要快得多。
  • 原作者 Matt Dowle 所说的数据表目标是“它提供了 base R 的 data.frame 的高性能版本,具有语法和功能增强,易于使用、方便和编程速度。” .虽然这需要使用其他两个模块,但我认为这是临时的最佳答案,因为 pydatatable 团队开发了使用 in 运算符的能力。
  • 仍然太慢,无法从 1M 行中筛选出 1000 个 - 非常令人失望
【解决方案2】:

事实证明,当您将表达式列表传递给 python datatable 时,它会将它们评估为 or

所以你可以这样做:

import datatable
df = datatable.Frame(V1=['A','B','C','D'], V2=[1,2,3,4])

items = ['A','B']
df[[datatable.f.V1 == i for i in items],:]

请注意,对此有一些注意事项:文档中没有描述它,我绝对不知道它是否总是有效。此外,它也只能过滤一列 - 如果您尝试过滤 V1==A or V2==1 使用列表的方法会创建重复的行。

如果您需要做一些更高级的过滤,您可以调整列表中的过滤表达式,例如:

df[([(datatable.f.V1 == i) & (datatable.f.V2 >= 2) for i in items]),:]

这将只返回示例中的第二行,正如预期的那样。

【讨论】:

  • 知道为什么这不适用于!= 吗?即df[[datatable.f.V1 != i for i in items],:] 是否希望保留 V1 为“C”和“D”的行,而不是看起来像我们附加两个额外的行?
  • @Rafael 当我写这个答案时,我的措辞似乎相当懒惰。在您的情况下,它基本上过滤了 V1 不是 A 的所有行,然后是 V1 不是 B 的所有行。您可以运行 df[:,[datatable.f.V1 != i for i in items]] 以更好地了解表达式返回的内容。在您的情况下,您可以执行以下操作:df[sum([(datatable.f.V1 != i) for i in items]) == len(items),:]df[[ i not in items for i in df[:, 'V1'].to_numpy()],:],如果将一列转换为 numpy 不是问题。请注意,现在文档中有一个关于通过列表理解过滤数据表的部分:
【解决方案3】:

我在pydatatable 中没有找到in 函数;但是,您的用例有一个技巧:

items = ['A','B']
regex = f"{'|'.join(items)}"
df[f.V1.re_match(regex),:]


   V1   V2
  ▪▪▪▪  ▪▪▪▪
0   A   1
1   B   2
2 rows × 2 columns

这是对另一个问题的回答:link。我在文档中也找不到这个函数。希望随着时间的推移,文档会有所改进,并且还会包含更多功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-15
    • 2012-05-10
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多