Zan*_*nam 6 python python-3.8 py-datatable
如何过滤掉某个列中的值包含在列表中的行?
基本上这是我正在使用的代码:
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)
由于 Pydatatable 不明确支持对值列表进行过滤(请参阅功能请求),因此以下解决方案可能显得不太直观。尽管如此,它仍然完全执行了利用数据表连接函数进行此类过滤的操作:
ids = [9016, 9017]
f = dt.Frame(itemid = ids)
sfr.key = "itemid"
sfr_filtered = f[:, :, dt.join(sfr)]
Run Code Online (Sandbox Code Playgroud)
这些步骤包括:
但这里有一个问题:当前连接有限制 - 它只有左外连接,并且连接列(itemid在sfr上面的解决方案中)必须具有唯一值,否则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之前,上面显示的解决方案之一会针对值列表进行过滤。