Производительность str.strip для Pandas

Я думал, что третий вариант должен был стать самым быстрым способом разбить пробелы? Может ли кто-нибудь дать мне некоторые общие правила, которые я должен применять при работе с большими наборами данных? Я обычно использую .astype(str), но ясно, что это не стоит для столбцов, которые, как я знаю, уже являются объектами.

%%timeit
fcr['id'] = fcr['id'].astype(str).map(str.strip)
10 loops, best of 3: 47.8 ms per loop

%%timeit
fcr['id'] = fcr['id'].map(str.strip)
10 loops, best of 3: 25.2 ms per loop

%%timeit
fcr['id'] = fcr['id'].str.strip(' ')
10 loops, best of 3: 55.5 ms per loop

Ответ 1

Сначала рассмотрим разницу между .map(str.strip) и .str.strip() (второй и третий случай).
Поэтому вам нужно понять, что делает str.strip() под капотом: на самом деле он делает несколько map(str.strip), но использует пользовательскую функцию map, которая будет обрабатывать отсутствующие значения.
Поэтому, если .str.strip() больше, чем .map(str.strip), следует ожидать, что этот метод будет всегда медленнее (и, как вы показали, в вашем случае 2x медленнее).

Использование метода .str.strip() имеет свои преимущества при автоматической обработке NaN (или обработке других нестрочных значений). Предположим, что столбец "id" содержит значение NaN:

In [4]: df['id'].map(str.strip)
...
TypeError: descriptor 'strip' requires a 'str' object but received a 'float'

In [5]: df['id'].str.strip()
Out[5]:
0                   NaN
1                as asd
2        asdsa asdasdas
              ...
29997              asds
29998            as asd
29999    asdsa asdasdas
Name: id, dtype: object

Как указывает @EdChum, вы действительно можете использовать map(str.strip), если вы уверены, что у вас нет значений NaN, если важна разница в производительности.


Возвращаясь к другой разности fcr['id'].astype(str).map(str.strip). Если вы уже знаете, что значения внутри серии являются строками, вызов astype(str), конечно, лишний. И именно этот вызов объясняет разницу:

In [74]: %timeit df['id'].astype(str).map(str.strip)
100 loops, best of 3: 10.5 ms per loop

In [75]: %timeit df['id'].astype(str)
100 loops, best of 3: 5.25 ms per loop

In [76]: %timeit df['id'].map(str.strip)
100 loops, best of 3: 5.18 ms per loop

Обратите внимание, что в случае, если у вас есть нестроковые значения (NaN, числовые значения,...), использование .str.strip() и .astype(str).map(str) не даст такого же результата:

In [11]: s = pd.Series(['  a', 10])

In [12]: s.astype(str).map(str.strip)
Out[12]:
0     a
1    10
dtype: object

In [13]: s.str.strip()
Out[13]:
0      a
1    NaN
dtype: object

Как вы можете видеть, .str.strip() вернет нестроковые значения как NaN вместо преобразования их в строки.