r语言 - 如何在python中从数据表中选择除一个(或两个)之外的所有列



在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]

最新更新