Python 如何删除numpy数组中的前置遮罩元素?

Python 如何删除numpy数组中的前置遮罩元素?,python,python-3.x,numpy,Python,Python 3.x,Numpy,如何从numpy数组中删除前导掩码元素。 例如,下面[2 x 5]的屏蔽数组: m_arr = [[- - 1 - 1] [1 - - 1 1]] 删除前导屏蔽元素的输出将为 m_arr = [[1 - 1] [1 - - 1 1]] 我试着用压缩列表作为理解工具 [m.compressed.tolist() for m in m_arr] 但即使做np也没有解决办法。沿轴应用 好,制作蒙版数组: In [96]: m_arr=np.ma.MaskedArray(np.

如何从numpy数组中删除前导掩码元素。 例如,下面[2 x 5]的屏蔽数组:

m_arr = [[- - 1 - 1]
     [1 - - 1 1]]
删除前导屏蔽元素的输出将为

m_arr = [[1 - 1]
     [1 - - 1 1]]
我试着用压缩列表作为理解工具

[m.compressed.tolist() for m in m_arr]

但即使做np也没有解决办法。沿轴应用

好,制作蒙版数组:

In [96]: m_arr=np.ma.MaskedArray(np.arange(10).reshape(2,5),np.array([[1,1,0,1,0
    ...: ],[0,1,1,0,0]]))
In [97]: m_arr
Out[97]: 
masked_array(
  data=[[--, --, 2, --, 4],
        [5, --, --, 8, 9]],
  mask=[[ True,  True, False,  True, False],
        [False,  True,  True, False, False]],
  fill_value=999999)
迭代时请查看1d数组属性:

In [99]: [(m.data,m.mask) for m in m_arr]
Out[99]: 
[(array([0, 1, 2, 3, 4]), array([ True,  True, False,  True, False])),
 (array([5, 6, 7, 8, 9]), array([False,  True,  True, False, False]))]
探索一个面具:

In [100]: m_arr[0].mask
Out[100]: array([ True,  True, False,  True, False])
In [101]: np.logical_and.accumulate(m_arr[0].mask)
Out[101]: array([ True,  True, False, False, False])
In [104]: m_arr[0][~_101]
Out[104]: 
masked_array(data=[2, --, 4],
             mask=[False,  True, False],
       fill_value=999999)
将其包装在函数中:

In [109]: def foo(m):
     ...:     mm = m.mask
     ...:     mm = ~np.logical_and.accumulate(mm)
     ...:     return m[mm]
     ...: 
并逐行应用它:

In [110]: [foo(m) for m in m_arr]
Out[110]: 
[masked_array(data=[2, --, 4],
              mask=[False,  True, False],
        fill_value=999999),
 masked_array(data=[5, --, --, 8, 9],
              mask=[False,  True,  True, False, False],
        fill_value=999999)]
In [132]: np.logical_and.accumulate(m_arr.mask)
Out[132]: 
array([[ True,  True, False,  True, False],
       [False,  True, False, False, False]])
====

在后续问题中,您尝试将
逻辑单元和
应用于整个数组(而不是逐行):

正确的应用程序-按行:

In [133]: np.logical_and.accumulate(m_arr.mask, axis=1)
Out[133]: 
array([[ True,  True, False, False, False],
       [False, False, False, False, False]])
始终使用布尔掩码将结果展平。我们已经清楚地表明,结果不可能是2d的——至少在每行的真值数量不同的一般情况下不是这样

In [134]: m_arr[~_]
Out[134]: 
masked_array(data=[2, --, 4, 5, --, --, 8, 9],
             mask=[False,  True, False, False,  True,  True, False, False],
       fill_value=999999)

好的,制作蒙版数组:

In [96]: m_arr=np.ma.MaskedArray(np.arange(10).reshape(2,5),np.array([[1,1,0,1,0
    ...: ],[0,1,1,0,0]]))
In [97]: m_arr
Out[97]: 
masked_array(
  data=[[--, --, 2, --, 4],
        [5, --, --, 8, 9]],
  mask=[[ True,  True, False,  True, False],
        [False,  True,  True, False, False]],
  fill_value=999999)
迭代时请查看1d数组属性:

In [99]: [(m.data,m.mask) for m in m_arr]
Out[99]: 
[(array([0, 1, 2, 3, 4]), array([ True,  True, False,  True, False])),
 (array([5, 6, 7, 8, 9]), array([False,  True,  True, False, False]))]
探索一个面具:

In [100]: m_arr[0].mask
Out[100]: array([ True,  True, False,  True, False])
In [101]: np.logical_and.accumulate(m_arr[0].mask)
Out[101]: array([ True,  True, False, False, False])
In [104]: m_arr[0][~_101]
Out[104]: 
masked_array(data=[2, --, 4],
             mask=[False,  True, False],
       fill_value=999999)
将其包装在函数中:

In [109]: def foo(m):
     ...:     mm = m.mask
     ...:     mm = ~np.logical_and.accumulate(mm)
     ...:     return m[mm]
     ...: 
并逐行应用它:

In [110]: [foo(m) for m in m_arr]
Out[110]: 
[masked_array(data=[2, --, 4],
              mask=[False,  True, False],
        fill_value=999999),
 masked_array(data=[5, --, --, 8, 9],
              mask=[False,  True,  True, False, False],
        fill_value=999999)]
In [132]: np.logical_and.accumulate(m_arr.mask)
Out[132]: 
array([[ True,  True, False,  True, False],
       [False,  True, False, False, False]])
====

在后续问题中,您尝试将
逻辑单元和
应用于整个数组(而不是逐行):

正确的应用程序-按行:

In [133]: np.logical_and.accumulate(m_arr.mask, axis=1)
Out[133]: 
array([[ True,  True, False, False, False],
       [False, False, False, False, False]])
始终使用布尔掩码将结果展平。我们已经清楚地表明,结果不可能是2d的——至少在每行的真值数量不同的一般情况下不是这样

In [134]: m_arr[~_]
Out[134]: 
masked_array(data=[2, --, 4, 5, --, --, 8, 9],
             mask=[False,  True, False, False,  True,  True, False, False],
       fill_value=999999)

您可以做与之相同的事情,并建议使用适当的应用程序,而不是自己编写循环

每行中第一个
False
的开头由

start = np.argmin(m_arr.mask, axis=1)
将其与每行中的零合并,并线性化索引以获得一些分割点:

pad = np.zeros(m_arr.shape[0], dtype=int)
indices = np.ravel(np.stack((pad, start), axis=-1) + np.arange(m_arr.shape[0])[:, None] * m_arr.shape[1])
然后,可以拆分展开阵列的遮罩部分和未遮罩部分:

m_arr = np.split(m_arr.ravel(), indices)[2::2]
定时

在本例中不是特别有趣,但我对以下函数的几个调用进行了基准测试:

def foo(m):
    mm = m.mask
    mm = ~np.logical_and.accumulate(mm)
    return m[mm]

def bar_hpaulj(x):
    return [foo(m) for m in x]

def bar_MadPhysicist(x):
    return np.split(x.ravel(), (np.stack((np.zeros(x.shape[0], dtype=int), np.argmin(x.mask, axis=1)), axis=-1) + np.arange(x.shape[0])[:, None] * x.shape[1]).ravel()
)[2::2]
数组被生成为
{10100100010000}
n
的随机平方:

m_arr = np.ma.MaskedArray(np.ones((n, n)), mask=np.random.randint(2, size=(n, n), dtype=bool))
时间安排如下:

  n   |     bar_hpaulj    |  bar_MadPhysicist |
------+-------------------+-------------------+
   10 |  464 µs ± 1.54 µs |  966 µs ± 3.06 µs |
------+-------------------+-------------------+
  100 | 4.69 ms ± 20.2 µs | 8.31 ms ± 26.3 µs |
------+-------------------+-------------------+
 1000 |   67 ms ± 1.09 ms |  83.2 ms ± 309 µs |
------+-------------------+-------------------+
10000 |  2.38 s ± 29.5 ms |  835 ms ± 3.14 ms |
------+-------------------+-------------------+

您可以做与之相同的事情,并建议使用适当的应用程序,而不是自己编写循环

每行中第一个
False
的开头由

start = np.argmin(m_arr.mask, axis=1)
将其与每行中的零合并,并线性化索引以获得一些分割点:

pad = np.zeros(m_arr.shape[0], dtype=int)
indices = np.ravel(np.stack((pad, start), axis=-1) + np.arange(m_arr.shape[0])[:, None] * m_arr.shape[1])
然后,可以拆分展开阵列的遮罩部分和未遮罩部分:

m_arr = np.split(m_arr.ravel(), indices)[2::2]
定时

在本例中不是特别有趣,但我对以下函数的几个调用进行了基准测试:

def foo(m):
    mm = m.mask
    mm = ~np.logical_and.accumulate(mm)
    return m[mm]

def bar_hpaulj(x):
    return [foo(m) for m in x]

def bar_MadPhysicist(x):
    return np.split(x.ravel(), (np.stack((np.zeros(x.shape[0], dtype=int), np.argmin(x.mask, axis=1)), axis=-1) + np.arange(x.shape[0])[:, None] * x.shape[1]).ravel()
)[2::2]
数组被生成为
{10100100010000}
n
的随机平方:

m_arr = np.ma.MaskedArray(np.ones((n, n)), mask=np.random.randint(2, size=(n, n), dtype=bool))
时间安排如下:

  n   |     bar_hpaulj    |  bar_MadPhysicist |
------+-------------------+-------------------+
   10 |  464 µs ± 1.54 µs |  966 µs ± 3.06 µs |
------+-------------------+-------------------+
  100 | 4.69 ms ± 20.2 µs | 8.31 ms ± 26.3 µs |
------+-------------------+-------------------+
 1000 |   67 ms ± 1.09 ms |  83.2 ms ± 309 µs |
------+-------------------+-------------------+
10000 |  2.38 s ± 29.5 ms |  835 ms ± 3.14 ms |
------+-------------------+-------------------+

我认为蒙面阵列帮不了你。逐行分别使用
数据
掩码
。在发布所需输出时,numpy中不能有非矩形数组。你需要使用一个不同的数据结构,比如列表。如果你可以使用一个一维数组和另一个索引数组来拆分它,这还不错。我认为掩蔽数组对你没有帮助。逐行分别使用
数据
掩码
。在发布所需输出时,numpy中不能有非矩形数组。您需要使用不同的数据结构,如列表。如果您可以使用1D数组和另一个索引数组来拆分它,这并不太糟糕。在数组变得非常大之前,您的数据结构会更快。我猜循环的开销终于赶上了索引。在数组变得非常大之前,你的循环会更快。我猜循环的开销终于赶上了索引。