在对象数据类型的重新排列中删除具有 nan 值的行
Removing rows with nan values in recarrays of object datatype
这是我的输入:
data = np.array ( [ ( 'a2', 'b1', 'c1' ), ( 'a1', 'b1', 'c1' ), ( 'a2', np.NaN, 'c2' ) ], dtype = [ ( 'A', 'O' ), ( 'B', 'O' ), ( 'C', 'O' ) ] ) . view ( np.recarray)
我想要这个作为输出:
rec.array ( [ ( 'a2', 'b1', 'c1' ), ( 'a1', 'b1', 'c1' ) ], dtype = [ ( 'A', 'O'), ( 'B', 'O' ), ( 'C', 'O' ) ] )
我试过:
data [ data [ 'B' ] ! = np.NaN ] . view ( np.recarray )
但它不起作用。
data [ data [ 'A' ] ! = 'a2' ] . view ( np.recarray )
给出了想要的输出。
为什么此方法不适用于 np.NaN
?如何删除对象数据类型的重新排列中包含 np.NaN
值的行?此外,~np.isnan()
不适用于对象数据类型。
定义一个应用 np.isnan
但不阻塞字符串的函数:
def foo(item):
try:
return np.isnan(item)
except TypeError:
return False
并使用 vectorize
创建一个将其应用于数组元素的函数,以及 return 一个布尔数组:
f=np.vectorize(foo, otypes=[bool])
你的 data
:
In [240]: data = np.array ( [ ( 'a2', 'b1', 'c1' ), ( 'a1', 'b1', 'c1' ), ( 'a2' , np.NaN, 'c2' ) ], dtype = [ ( 'A', 'O' ), ( 'B', 'O' ), ( 'C', 'O' ) ] )
In [241]: data
Out[241]:
array([('a2', 'b1', 'c1'), ('a1', 'b1', 'c1'), ('a2', nan, 'c2')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
In [242]: data['B']
Out[242]: array(['b1', 'b1', nan], dtype=object)
In [243]: f(data['B'])
Out[243]: array([False, False, True], dtype=bool)
In [244]: data[~f(data['B'])]
Out[244]:
array([('a2', 'b1', 'c1'), ('a1', 'b1', 'c1')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
==============
对所有字段执行此测试删除的最简单方法是仅迭代字段名称:
In [429]: data # expanded with more nan
Out[429]:
array([('a2', 'b1', 'c1'), ('a1', 'b1', 'c1'), ('a2', nan, 'c2'),
('a2', 'b1', nan), (nan, 'b1', 'c1')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
将f
函数应用于每个字段并收集到一个数组中:
In [441]: np.array([f(data[name]) for name in data.dtype.names])
Out[441]:
array([[False, False, False, False, True],
[False, False, True, False, False],
[False, False, False, True, False]], dtype=bool)
使用 any
获取任何项目为 True 的列:
In [442]: np.any(_, axis=0)
Out[442]: array([False, False, True, True, True], dtype=bool)
In [443]: data[_] # the ones with nan
Out[443]:
array([('a2', nan, 'c2'), ('a2', 'b1', nan), (nan, 'b1', 'c1')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
In [444]: data[~__] # the ones without
Out[444]:
array([('a2', 'b1', 'c1'), ('a1', 'b1', 'c1')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
(在 Ipython _
和 __
中包含前面 Out
行中显示的结果。)
tolist
将数组转换为元组列表(结构化数组的记录显示为元组):
In [448]: data.tolist()
Out[448]:
[('a2', 'b1', 'c1'),
('a1', 'b1', 'c1'),
('a2', nan, 'c2'),
('a2', 'b1', nan),
(nan, 'b1', 'c1')]
f
作为 vectorized
函数能够将 foo
应用于每个元素(显然是 np.array(data.tolist(), dtype=object)
)
In [449]: f(data.tolist())
Out[449]:
array([[False, False, False],
[False, False, False],
[False, True, False],
[False, False, True],
[ True, False, False]], dtype=bool)
In [450]: np.any(_, axis=1)
Out[450]: array([False, False, True, True, True], dtype=bool)
我以前从未尝试过 tolist
和 vectorize
的这种组合。矢量化函数对其输入进行迭代,因此与显式迭代相比,它们并没有提供太多速度优势,但对于像这样的任务,它确实简化了编码。
另一种可能性是定义foo
以跨记录的字段进行操作。事实上,当我尝试将 f
应用于单个记录时,我发现了 tolist
技巧:
In [456]: f(data[2])
Out[456]: array(False, dtype=bool)
In [458]: f(list(data[2]))
Out[458]: array([False, True, False], dtype=bool)
In [459]: f(data[2].tolist())
Out[459]: array([False, True, False], dtype=bool)
这是我的输入:
data = np.array ( [ ( 'a2', 'b1', 'c1' ), ( 'a1', 'b1', 'c1' ), ( 'a2', np.NaN, 'c2' ) ], dtype = [ ( 'A', 'O' ), ( 'B', 'O' ), ( 'C', 'O' ) ] ) . view ( np.recarray)
我想要这个作为输出:
rec.array ( [ ( 'a2', 'b1', 'c1' ), ( 'a1', 'b1', 'c1' ) ], dtype = [ ( 'A', 'O'), ( 'B', 'O' ), ( 'C', 'O' ) ] )
我试过:
data [ data [ 'B' ] ! = np.NaN ] . view ( np.recarray )
但它不起作用。
data [ data [ 'A' ] ! = 'a2' ] . view ( np.recarray )
给出了想要的输出。
为什么此方法不适用于 np.NaN
?如何删除对象数据类型的重新排列中包含 np.NaN
值的行?此外,~np.isnan()
不适用于对象数据类型。
定义一个应用 np.isnan
但不阻塞字符串的函数:
def foo(item):
try:
return np.isnan(item)
except TypeError:
return False
并使用 vectorize
创建一个将其应用于数组元素的函数,以及 return 一个布尔数组:
f=np.vectorize(foo, otypes=[bool])
你的 data
:
In [240]: data = np.array ( [ ( 'a2', 'b1', 'c1' ), ( 'a1', 'b1', 'c1' ), ( 'a2' , np.NaN, 'c2' ) ], dtype = [ ( 'A', 'O' ), ( 'B', 'O' ), ( 'C', 'O' ) ] )
In [241]: data
Out[241]:
array([('a2', 'b1', 'c1'), ('a1', 'b1', 'c1'), ('a2', nan, 'c2')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
In [242]: data['B']
Out[242]: array(['b1', 'b1', nan], dtype=object)
In [243]: f(data['B'])
Out[243]: array([False, False, True], dtype=bool)
In [244]: data[~f(data['B'])]
Out[244]:
array([('a2', 'b1', 'c1'), ('a1', 'b1', 'c1')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
==============
对所有字段执行此测试删除的最简单方法是仅迭代字段名称:
In [429]: data # expanded with more nan
Out[429]:
array([('a2', 'b1', 'c1'), ('a1', 'b1', 'c1'), ('a2', nan, 'c2'),
('a2', 'b1', nan), (nan, 'b1', 'c1')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
将f
函数应用于每个字段并收集到一个数组中:
In [441]: np.array([f(data[name]) for name in data.dtype.names])
Out[441]:
array([[False, False, False, False, True],
[False, False, True, False, False],
[False, False, False, True, False]], dtype=bool)
使用 any
获取任何项目为 True 的列:
In [442]: np.any(_, axis=0)
Out[442]: array([False, False, True, True, True], dtype=bool)
In [443]: data[_] # the ones with nan
Out[443]:
array([('a2', nan, 'c2'), ('a2', 'b1', nan), (nan, 'b1', 'c1')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
In [444]: data[~__] # the ones without
Out[444]:
array([('a2', 'b1', 'c1'), ('a1', 'b1', 'c1')],
dtype=[('A', 'O'), ('B', 'O'), ('C', 'O')])
(在 Ipython _
和 __
中包含前面 Out
行中显示的结果。)
tolist
将数组转换为元组列表(结构化数组的记录显示为元组):
In [448]: data.tolist()
Out[448]:
[('a2', 'b1', 'c1'),
('a1', 'b1', 'c1'),
('a2', nan, 'c2'),
('a2', 'b1', nan),
(nan, 'b1', 'c1')]
f
作为 vectorized
函数能够将 foo
应用于每个元素(显然是 np.array(data.tolist(), dtype=object)
)
In [449]: f(data.tolist())
Out[449]:
array([[False, False, False],
[False, False, False],
[False, True, False],
[False, False, True],
[ True, False, False]], dtype=bool)
In [450]: np.any(_, axis=1)
Out[450]: array([False, False, True, True, True], dtype=bool)
我以前从未尝试过 tolist
和 vectorize
的这种组合。矢量化函数对其输入进行迭代,因此与显式迭代相比,它们并没有提供太多速度优势,但对于像这样的任务,它确实简化了编码。
另一种可能性是定义foo
以跨记录的字段进行操作。事实上,当我尝试将 f
应用于单个记录时,我发现了 tolist
技巧:
In [456]: f(data[2])
Out[456]: array(False, dtype=bool)
In [458]: f(list(data[2]))
Out[458]: array([False, True, False], dtype=bool)
In [459]: f(data[2].tolist())
Out[459]: array([False, True, False], dtype=bool)