Нарезка Numpy/Pandas на основе интервалов

Попытка найти способ нарезать несмежные и неравные по длине строки матрицы pandas/numpy, чтобы я мог установить значения в общее значение. Кто-нибудь встречал элегантное решение для этого?

import numpy as np
import pandas as pd
x = pd.DataFrame(np.arange(12).reshape(3,4))
#x is the matrix we want to index into

"""
x before:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
"""
y = pd.DataFrame([[0,3],[2,2],[1,2],[0,0]]) 
#y is a matrix where each row contains a start idx and end idx per column of x

"""
   0  1
0  0  3
1  2  3
2  1  3
3  0  1
"""

То, что я ищу, - это способ эффективно выбирать фрагменты разной длины x на основе строк y.

x[y] = 0 
"""
x afterwards:
array([[ 0,  1,  2,  0],
       [ 0,  5,  0,  7],
       [ 0,  0,  0, 11]])

person Brian    schedule 27.04.2021    source источник
comment
Возможно, вы ищете маскирование   -  person ti7    schedule 27.04.2021
comment
для цикла назначить обратно   -  person BENY    schedule 27.04.2021
comment
спасибо @ti7, я думаю, что маска напрямую здесь не сработает, поскольку условие не обязательно одно логическое значение, а из списка интервалов   -  person Brian    schedule 27.04.2021
comment
цикл for - это текущий подход, с которым я работаю, но он медленный.   -  person Brian    schedule 27.04.2021


Ответы (2)


Маскирование все еще может быть полезным, потому что даже если цикла нельзя полностью избежать, основной фрейм данных x не нужно будет вовлекать в цикл, так что это должно ускорить процесс:

mask = np.zeros_like(x, dtype=bool)

for i in range(len(y)):
    mask[y.iloc[i, 0]:(y.iloc[i, 1] + 1), i] = True
    
x[mask] = 0
x
    0   1   2   3
0   0   1   2   0
1   0   5   0   7
2   0   0   0   11

В качестве дальнейшего улучшения рассмотрите возможность определения y как массива NumPy, если это возможно.

person Arne    schedule 27.04.2021

Я настроил этот ответ на вашу проблему:

y_t = y.values.transpose()
y_t[1,:] = y_t[1,:] - 1 # or remove this line and change '>= r' below to '> r`

r = np.arange(x.shape[0])

mask = ((y_t[0,:,None] <= r) & (y_t[1,:,None] >= r)).transpose()

res = x.where(~mask, 0)
res
#     0   1   2   3
# 0   0   1   2   0
# 1   0   5   0   7
# 2   0   0   0   11
person AlexK    schedule 27.04.2021