根据是否在列表中过滤python数据表的行

Zan*_*nam 6 python python-3.8 py-datatable

我是使用 python 数据表的新手,这是我正在关注的教程

如何过滤掉某个列中的值包含在列表中的行?

基本上这是我正在使用的代码:

    import datatable as dt
    sfr = dt.fread(os.path.join(dirName, 'Results.csv'))

sfr
Out[25]: 
         |       ioid  itemtype  date       itemid           tid  value
-------- + ----------  --------  --------  -------  ------------  -------
       0 |          1         1  7-1-2022     9015           531   0.0283
       1 |          1         1  7-1-2022     9015           532   0.0071
       2 |          1         1  7-1-2022     9016           534   0.0065
       3 |          1         1  7-1-2022     9017          1018   0.0005
Run Code Online (Sandbox Code Playgroud)

我正在尝试执行以下操作

ids = [9016, 9017]
sft[dt.f.itemid.isin(ids)]
Run Code Online (Sandbox Code Playgroud)

但是,我无法使语法起作用。

期望的输出是:

         |       ioid  itemtype  date       itemid           tid  value
-------- + ----------  --------  --------  -------  ------------  -------
       2 |          1         1  7-1-2022     9016           534   0.0065
       3 |          1         1  7-1-2022     9017          1018   0.0005
Run Code Online (Sandbox Code Playgroud)

top*_*hef 4

由于 Pydatatable 不明确支持对值列表进行过滤(请参阅功能请求),因此以下解决方案可能显得不太直观。尽管如此,它仍然完全执行了利用数据表连接函数进行此类过滤的操作:

ids = [9016, 9017]
f = dt.Frame(itemid = ids)
sfr.key = "itemid"
sfr_filtered = f[:, :, dt.join(sfr)]
Run Code Online (Sandbox Code Playgroud)

这些步骤包括:

  1. 创建一个框架(数据表),其中包含与要过滤的列同名的单个列,并在此框架内存储值列表
  2. 在正在过滤的列上键入原始帧
  3. 使用数据表连接连接帧以执行过滤

但这里有一个问题:当前连接有限制 - 它只有左外连接,并且连接列(itemidsfr上面的解决方案中)必须具有唯一值,否则sfr.key = "itemid"会引发此错误:

ValueError:无法设置键:值不唯一

itemid由于这些强有力的假设,当包含不唯一的值时,它将不起作用。在这种情况下,我们扭转连接并在添加到包含列表的框架中的虚拟列上添加额外的过滤器:

ids = [9016, 9017]
f = dt.Frame(itemid = ids, dummy = [0, 0])
f.key = "itemid"
sfr_filtered = sfr[:, :, dt.join(f)][~dt.isna(dt.f.dummy), :]
Run Code Online (Sandbox Code Playgroud)

该解决方案始终有效,但显然效率较低,因为总是连接所有行并进行额外的过滤以删除不匹配的行。有关 Pydatatable join 当前状态的更多详细信息,您可以在此处找到文档。

更新

为了完整起见,我添加了另一个(可以说更直接的)解决方案,该解决方案借自Pasha(Pydatatable 的创建者和维护者)的这个答案:

import functools
import operator

filter = functools.reduce(operator.or_, (dt.f.itemid == id for id in ids))
sfr[filter, :]
Run Code Online (Sandbox Code Playgroud)

在实现此功能请求https://github.com/h2oai/datatable/issues/699之前,上面显示的解决方案之一会针对值列表进行过滤。

  • 是的,functools.reduce 是最简单的。我写了一篇关于[过滤pydatatable中的行](https://samukweku.github.io/data-wrangling/python_datatable_row_selection.html#filtering-rows-based-on-multiple-conditions)的文章,这可能会有所帮助 (2认同)