Основываясь на комментариях, я провел основной эксперимент по сложности времени между двумя предложенными методами.Обратите внимание, что это не относится ни к каким случаям, когда ваш подход терпит неудачу, поскольку я не нашел ни одного.
Настройка:
def make_col():
return [np.random.choice([1,2,3,4,5,6,7,8,9,10,np.NaN]) for i in range(100000)]
df=pd.DataFrame({k:make_ops() for k in list('abcdefghijklmnopqrstuvwxyz')})
df.shape
(100000, 26)
Эксперимент (обратите внимание, что я пытался быть явным на каждомшаг, а не оптимизация для общей эффективности, чтобы показать разницу между ними):
%%timeit
n=[]
for col in df.columns:
count=len([x for x in df[col] if x != x])
n.append(count)
134 ms
%%timeit
n=[]
for col in df.columns:
count=count = df[col].isnull().sum()
n.append(count)
29.7 ms
Для улучшения примерно на 80% с использованием встроенных методов
Интересно, на основе NumPy /Оптимизация Cython / C под капотом: если вы запустите профилировщик %%prun
для обеих вышеперечисленных операций, вы получите меньше отдельных вызовов функций с вашим подходом, но больше общее время выполнения.Соответственно:
2013 function calls in 0.248 seconds
против.
8903 function calls in 0.046 seconds
И в отношении использования памяти между ними, похоже, вы правы в том, что оба логически эквивалентны в отношении копирования и хранения.Оба приведенных выше фрагмента примерно
peak memory: 247.20 MiB
с использованием магии %%memit
из этого источника (который, как предостережение, я не видел и не использовал ранееи я не в курсе каких-либо ошибок или проблем, связанных с его использованием)