作为一个for循环俱乐部的成员,我建议使用Python的C加速例程——itertools.chain
和collections.Counter
——以提高性能。
from itertools import chain
from collections import Counter
pd.Series(
Counter(chain.from_iterable(x.split('|') for x in df.Genre)))
Adventure 1
Animation 1
Children 1
Comedy 2
Fantasy 1
Romance 1
dtype: int64
为什么我认为CPython函数比pandas的“矢量化”字符串函数更好?它们本质上很难矢量化。你可以在For loops with pandas - When should I care?中了解更多。
如果你必须处理NaN,你可以调用一个能优雅地处理异常的函数:
def try_split(x):
try:
return x.split('|')
except AttributeError:
return []
pd.Series(
Counter(chain.from_iterable(try_split(x) for x in df.Genre)))
通俗易懂地说,你可以使用
split
,
stack
, 和
value_counts
来实现这个功能。
df['Genre'].str.split('|', expand=True).stack().value_counts()
Comedy 2
Romance 1
Children 1
Animation 1
Fantasy 1
Adventure 1
dtype: int64
即使是微小的数据框,时间差异也很明显。
%timeit df['Genre'].str.get_dummies(sep='|').sum()
%timeit df['Genre'].str.split('|', expand=True).stack().value_counts()
%%timeit
pd.Series(
Counter(chain.from_iterable(try_split(x) for x in df.Genre)))
2.8 ms ± 68.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.4 ms ± 210 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
320 µs ± 9.71 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)