Многие методы были представлены здесь, и я не мог устоять. Мне пришлось провести небольшое сравнение производительности между этими:
%timeit vivek_kumar()
16.6 ms ± 495 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit numbered_user()
6.69 ms ± 116 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit warpri()
14 ms ± 216 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit jpp()
2.21 ms ± 96.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit wen()
991 µs ± 20.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit pirsquared()
938 µs ± 24.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Это сравнение было выполнено на фрейме данных длиной 80 тыс. Строк для проверки масштабируемости. Казалось бы, решения wen
и piRsquared
являются наиболее эффективными. Не стесняйтесь задавать эти ответы.
РЕДАКТИРОВАТЬ: для прозрачности здесь приведены функции, используемые для выполнения теста:
def vivek_kumar():
data = df.copy()
first_index = data.loc[data['Col_A'] == 0, 'Col_A'].index[0]
data.loc[:first_index, 'Col_B'] = False
data.loc[first_index:, 'Col_B'] = True
def numbered_user():
data = df.copy()
idx = data.Col_A.eq(0).idxmax()
data['Col_B'] = False
data.loc[idx:, 'Col_B'] = True
def warpri():
data = df.copy()
def update_col_b(col_a):
return col_a == 0
data['Col_B'] = data.Col_A.apply(update_col_b)
def jpp():
data = df.copy()
idx = next((i for i, j in enumerate(data['Col_A']) if j == 0), len(data['Col_A']))
data['Col_B'] = ~(data.index < idx)
def wen():
data = df.copy()
data['Col_B'] = data.Col_A.eq(0).cummax()
def pirsquared():
data = df.copy()
# This would return a copy. My preferred approach
# return data.assign(Col_B=np.logical_or.accumulate(data.Col_A.values == 0))
# This edits the dataframe in place but properly compares against the other proposals
df['Col_B'] = np.logical_or.accumulate(data.Col_A.values == 0)
EDIT2: Следуя указаниям piRSquared, здесь также проводится сравнение между использованием assign
для создания копии кадра данных и использованием =
для изменения существующего кадра данных:
def pirsquared1():
data = df.copy()
data = data.assign(Col_B=np.logical_or.accumulate(data.Col_A.values == 0))
%timeit pirsquared1()
923 µs ± 32.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
def pirsquared2():
data = df.copy()
df['Col_B'] = np.logical_or.accumulate(data.Col_A.values == 0)
%timeit pirsquared2()
598 µs ± 35.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)