在R数据中。表中,我可以排除如下列
library(data.table)
foo <- data.table(x = c(1,2,3), y = c(4, 5, 6), z = c(7, 8, 9))
print(foo)
x y z
1: 1 4 7
2: 2 5 8
3: 3 6 9
# exclude one column
foo[, !"x"]
y z
1: 4 7
2: 5 8
3: 6 9
# exclude two columns
foo[, !c("x", "y")]
z
1: 7
2: 8
3: 9
我如何在Python数据表中做同样的事情?
import datatable as dt # v 1.0.0
foo = dt.Frame({'x': [1,2,3], 'y': [4,5,6], 'z': [7,8,9]})
print(foo)
| x y z
| int32 int32 int32
-- + ----- ----- -----
0 | 1 4 7
1 | 2 5 8
2 | 3 6 9
[3 rows x 3 columns]
# exclude one column
foo[:, !"x"] # error
foo[:, !["x"]] # error
foo[:, !f.x] # error
# exclude two columns
编辑很抱歉没有明确地说明这一点,但我知道一个明显的解决方案-做一个包含语句,我建立一个我想要包含的所有列的列表并使用它,而不是一个排除语句,我使用一个列列表来排除。然而,我发现包含技术很笨拙/麻烦,读和写起来不太自然。因此,我特别寻求一种排除解决方案,就像在data.table
中实现的那样。
关于如何取消选择行/列的文档中列出了这些方法。
列表构建方法
names
过滤值的理解:
cols = ["x"]
foo_filtered = foo[:, [name for name in foo.names if name not in cols]]
或等效的filter
:
cols = ["x"]
foo_filtered = foo[:, list(filter(lambda n: n not in cols, foo.names))]
带有布尔值列表:
cols = ["x"]
foo_filtered = foo[:, [n not in cols for n in foo.names]]
或等价的map
:
cols = ["x"]
foo_filtered = foo[:, list(map(lambda n: n not in cols, foo.names))]
foo_filtered
:
| y z
| int32 int32
-- + ----- -----
0 | 4 7
1 | 5 8
2 | 6 9
[3 rows x 2 columns]
排除方法
也可以使用remove
,但是,这仅限于列选择:
from datatable import f
foo[:, f[:].remove(f['x', 'y'])]
| z
| int32
-- + -----
0 | 7
1 | 8
2 | 9
[3 rows x 1 column]
这个方法不是来自文档。
子类方法
如果模糊列表理解是目标,我们可以为tuple
制作一个包装器,可以用来为names
添加额外的行为。也就是说,使用xor
(或其他所需的操作)作为"排除操作符"。
(我选择了xor
,因为pandas
列过去允许此操作符排除列)
这个自定义的tuple
可以和dt.Frame
的子类一起使用来包装属性names
:
from __future__ import annotations
import datatable as dt # v 1.0.0
class TableColumns(tuple):
def __xor__(self, other) -> TableColumns:
if isinstance(other, str):
output = [n != other for n in self]
elif any(isinstance(other, i) for i in [tuple, list, set]):
output = [n not in other for n in self]
else:
raise TypeError(
f'Unsupported type {type(other)} used to filter names'
)
return TableColumns(output)
class MyFrame(dt.Frame):
@property
def names(self) -> TableColumns:
return TableColumns(super(MyFrame, self).names)
过滤可以自然完成:
框架构造函数(使用子类):foo = MyFrame({'x': [1, 2, 3], 'y': [4, 5, 6], 'z': [7, 8, 9]})
filter WithList
:
foo_filtered = foo[:, foo.names ^ ['x', 'z']]
Tuple
:
foo_filtered = foo[:, foo.names ^ ('x', 'z')]
Set
:
foo_filtered = foo[:, foo.names ^ {'x', 'z'}]
foo_filtered
:
| y
| int32
-- + -----
0 | 4
1 | 5
2 | 6
[3 rows x 1 column]
不包含str
:
foo_filtered = foo[:, foo.names ^ 'x']
| y z
| int32 int32
-- + ----- -----
0 | 4 7
1 | 5 8
2 | 6 9
[3 rows x 2 columns]
使用列表推导式的可能解决方案:
>>> cols_to_exclude = ['x']
>>> print(foo[:, [col for col in foo.names if col not in cols_to_exclude]])
| z y
| int32 int32
-- + ----- -----
0 | 7 4
1 | 8 5
2 | 9 6
[3 rows x 2 columns]
可以使用datatable中的布尔值来选择数据,因此可以使用列表推导来生成所需的列选择布尔值。
本例中为foo[:, ["x" not in name for name in foo.names]]
>>> import datatable as dt
>>> foo = dt.Frame({'x': [1,2,3], 'y': [4,5,6], 'z': [7,8,9]})
>>> foo[:, ["x" not in name for name in foo.names]]
| y z
| int32 int32
-- + ----- -----
0 | 4 7
1 | 5 8
2 | 6 9
[3 rows x 2 columns]