Векторизованный код Python для итерации и изменения каждого столбца Pandas DataFrame в окне - PullRequest
0 голосов
/ 23 сентября 2018

У меня есть датафрейм из нулей и единиц.Я перебираю каждый столбец с помощью цикла.Если я получу один на итерации, я должен оставить его в столбце.Но если в следующих n позициях после этой есть некоторые, я должен превратить их в нули.Затем повторите то же самое до конца столбца, а затем повторите все это для каждого столбца.

Можно ли избавиться от цикла и векторизовать все с помощью операций с кадрами / матрицами / массивами в pandas / numpy?И как мне это сделать?n может быть где угодно от 2 до 100.

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

def clear_window(df, n):

    # create buffer of size n
    pad = pd.DataFrame(np.zeros([n, df.shape[1]]),
                       columns=df.columns)
    padded_df = pd.concat([pad, df])

    # compute rolling sum and cut off the buffer
    roll = (padded_df
            .rolling(n+1)
            .sum()
            .iloc[n:, :]
           )

    # delete ones where rolling sum is above 1 or below -1
    result = df * ((roll == 1.0) | (roll == -1.0)).astype(int)

    return result

1 Ответ

0 голосов
/ 27 сентября 2018

Numba поможет вам справиться с этими проблемами последовательного зацикливания, если вы не сможете найти способ векторизации.

Этот код перебирает каждую строку в поисках целевого значения.Когда целевое значение (1) найдено, следующим n строкам присваивается значение заполнения (0).Индекс строки поиска увеличивается, чтобы пропустить строки заполнения, и начинается следующий поиск.

from numba import jit

@jit(nopython=True)
def find_and_fill(arr, span, tgt_val=1, fill_val=0):
    start_idx = 0
    end_idx = arr.size
    while start_idx < end_idx:
        if arr[start_idx] == tgt_val:
            arr[start_idx + 1 : start_idx + 1 + span] = fill_val
            start_idx = start_idx + 1 + span
        else:
            start_idx = start_idx + 1
    return arr

df2 = df.copy()
# get the dataframe values into a numpy array
a = df2.values

# transpose and run the function for each column of the dataframe
for col in a.T:
    # fill span is set to 6 in this example
    col = find_and_fill(col, 6)

# assign the array back to the dataframe
df2[list(df2.columns)] = a

# df2 now contains the result values
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...