Python Установка значений без цикла - PullRequest
0 голосов
/ 21 декабря 2018

У меня есть фрейм данных временного ряда, в котором есть 1 или 0 (истина / ложь).Я написал функцию, которая перебирает все строки со значениями 1 в них.Если задан пользовательский целочисленный параметр с именем n_hold, я установлю значения от 1 до n строк вперед от начальной строки.

Например, в приведенном ниже кадре данных я буду циклически преобразовывать строку 2016-08-05.Если n_hold = 2, тогда я также установлю для 2016-08-08 и 2016-08-09 значение 1.:

2016-08-03    0
2016-08-04    0
2016-08-05    1
2016-08-08    0
2016-08-09    0
2016-08-10    0

В результате значение df будет

2016-08-03    0
2016-08-04    0
2016-08-05    1
2016-08-08    1
2016-08-09    1
2016-08-10    0

ПроблемаУ меня есть, это запускается десятки тысяч раз, и мое текущее решение, где я зацикливаюсь на рядах, где есть и поднаборы слишком медленные.Мне было интересно, есть ли какие-либо решения для вышеуказанной проблемы, которые действительно бывают быстрыми.

Вот мое (медленное) решение, x - это начальный кадр данных сигнала:

n_hold = 2
entry_sig_diff = x.diff()
entry_sig_dt = entry_sig_diff[entry_sig_diff == 1].index
final_signal = x * 0
for i in range(0, len(entry_sig_dt)):
    row_idx = entry_sig_diff.index.get_loc(entry_sig_dt[i])

    if (row_idx + n_hold) >= len(x):
        break

    final_signal[row_idx:(row_idx + n_hold + 1)] = 1

1 Ответ

0 голосов
/ 21 декабря 2018

Полностью измененный ответ, потому что он работает по-разному с последовательными 1 значениями:

Объяснение :

Решение удаляет каждое последующее 1 сначала where с логической цепочкой, сравнивая с ne (не равно !=) с shift до NaN с, заполняя их на ffill с параметром limit и последней заменой 0 назад:

n_hold = 2
s = x.where(x.ne(x.shift()) & (x == 1)).ffill(limit=n_hold).fillna(0, downcast='int')

Синхронизация и сравнение выходов:

np.random.seed(123)
x = pd.Series(np.random.choice([0,1], p=(.8,.2), size=1000))
x1 = x.copy()
#print (x)


def orig(x):
    n_hold = 2
    entry_sig_diff = x.diff()
    entry_sig_dt = entry_sig_diff[entry_sig_diff == 1].index
    final_signal = x * 0
    for i in range(0, len(entry_sig_dt)):
        row_idx = entry_sig_diff.index.get_loc(entry_sig_dt[i])

        if (row_idx + n_hold) >= len(x):
            break

        final_signal[row_idx:(row_idx + n_hold + 1)] = 1
    return final_signal

#print (orig(x))

n_hold = 2
s = x.where(x.ne(x.shift()) & (x == 1)).ffill(limit=n_hold).fillna(0, downcast='int')
#print (s)

df = pd.concat([x,orig(x1), s], axis=1, keys=('input', 'orig', 'new'))
print (df.head(20))
    input  orig  new
0       0     0    0
1       0     0    0
2       0     0    0
3       0     0    0
4       0     0    0
5       0     0    0
6       1     1    1
7       0     1    1
8       0     1    1
9       0     0    0
10      0     0    0
11      0     0    0
12      0     0    0
13      0     0    0
14      0     0    0
15      0     0    0
16      0     0    0
17      0     0    0
18      0     0    0
19      0     0    0

#check outputs
#print (s.values == orig(x).values)

Синхронизация :

%timeit (orig(x))
24.8 ms ± 653 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit x.where(x.ne(x.shift()) & (x == 1)).ffill(limit=n_hold).fillna(0, downcast='int')
1.36 ms ± 12.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...