Я буду весить здесь, как я думаю, что это хорошее дело быстрее, чем любой из предложенных методов. argmin
дает индекс первого значения False
в каждой строке результата np.isnan
в векторном виде, что является трудной частью. Он по-прежнему опирается на цикл Python для извлечения значения, но внешний вид вверх очень быстро:
def get_first_non_null(df):
a = df.values
col_index = np.isnan(a).argmin(axis=1)
return [a[row, col] for row, col in enumerate(col_index)]
EDIT: Вот полностью Векторизованным решения, которое может быть много быстрее, опять же в зависимости от формы ввода , Обновленный бенчмаркинг ниже.
def get_first_non_null_vec(df):
a = df.values
n_rows, n_cols = a.shape
col_index = np.isnan(a).argmin(axis=1)
flat_index = n_cols * np.arange(n_rows) + col_index
return a.ravel()[flat_index]
Если строка полностью нулевая, то соответствующее значение также будет равно null. Вот некоторые бенчмаркинг против решения unutbu в:
df = pd.DataFrame(np.random.choice([1, np.nan], (10000, 1500), p=(0.01, 0.99)))
#%timeit df.stack().groupby(level=0).first().reindex(df.index)
%timeit get_first_non_null(df)
%timeit get_first_non_null_vec(df)
1 loops, best of 3: 220 ms per loop
100 loops, best of 3: 16.2 ms per loop
100 loops, best of 3: 12.6 ms per loop
In [109]:
df = pd.DataFrame(np.random.choice([1, np.nan], (100000, 150), p=(0.01, 0.99)))
#%timeit df.stack().groupby(level=0).first().reindex(df.index)
%timeit get_first_non_null(df)
%timeit get_first_non_null_vec(df)
1 loops, best of 3: 246 ms per loop
10 loops, best of 3: 48.2 ms per loop
100 loops, best of 3: 15.7 ms per loop
df = pd.DataFrame(np.random.choice([1, np.nan], (1000000, 15), p=(0.01, 0.99)))
%timeit df.stack().groupby(level=0).first().reindex(df.index)
%timeit get_first_non_null(df)
%timeit get_first_non_null_vec(df)
1 loops, best of 3: 326 ms per loop
1 loops, best of 3: 326 ms per loop
10 loops, best of 3: 35.7 ms per loop
Использование 'df' как глобальное здесь делает меня немного тошнотворным. На самом деле вам нужна комбинация ответа [@ yangjie] (http://stackoverflow.com/a/31828559/2071807) и этого. Я собираюсь опубликовать комбинацию, но не стесняйтесь просто украсть лучшие биты (если вы считаете, что они есть!) – LondonRob
@LondonRob Я думаю, что на самом деле он должен просто перебирать df один раз – EdChum
* Теперь * вы говорите , Теперь это действительно хорошо. +1 (почему бы просто не стереть вашу первую итерацию?) – LondonRob