"Reduce" 系列函数
"Reduce" function for Series
是否有 pandas 系列的 reduce
类似物?
例如,map
的类似物是 pd.Series.apply,但我找不到 reduce
的任何类似物。
我的应用是,我有一个pandas系列列表:
>>> business["categories"].head()
0 ['Doctors', 'Health & Medical']
1 ['Nightlife']
2 ['Active Life', 'Mini Golf', 'Golf']
3 ['Shopping', 'Home Services', 'Internet Servic...
4 ['Bars', 'American (New)', 'Nightlife', 'Loung...
Name: categories, dtype: object
我想使用 reduce
将列表系列合并在一起,如下所示:
categories = reduce(lambda l1, l2: l1 + l2, categories)
但这需要很长时间,因为将两个列表合并在一起是 O(n)
时间 Python。我希望 pd.Series
有一种矢量化的方式来更快地执行此操作。
在值
上有itertools.chain()
这可能会更快:
from itertools import chain
categories = list(chain.from_iterable(categories.values))
性能
from functools import reduce
from itertools import chain
categories = pd.Series([['a', 'b'], ['c', 'd', 'e']] * 1000)
%timeit list(chain.from_iterable(categories.values))
1000 loops, best of 3: 231 µs per loop
%timeit list(chain(*categories.values.flat))
1000 loops, best of 3: 237 µs per loop
%timeit reduce(lambda l1, l2: l1 + l2, categories)
100 loops, best of 3: 15.8 ms per loop
对于此数据集,chain
ing 速度大约快 68 倍。
向量化?
当你有原生的 NumPy 数据类型时,向量化就起作用了(pandas毕竟它的数据使用 NumPy)。由于我们已经在 Series 中有列表并且想要一个列表作为结果,因此矢量化不太可能加快速度。标准 Python 对象和 pandas/NumPy 数据类型之间的转换可能会耗尽您从矢量化中获得的所有性能。我曾尝试在另一个答案中对算法进行矢量化。
矢量化但速度慢
你可以使用 NumPy 的 concatenate
:
import numpy as np
list(np.concatenate(categories.values))
性能
但是我们已经有了列表,即 Python 个对象。因此矢量化必须在 Python 对象和 NumPy 数据类型之间来回切换。这让事情变慢:
categories = pd.Series([['a', 'b'], ['c', 'd', 'e']] * 1000)
%timeit list(np.concatenate(categories.values))
100 loops, best of 3: 7.66 ms per loop
%timeit np.concatenate(categories.values)
100 loops, best of 3: 5.33 ms per loop
%timeit list(chain.from_iterable(categories.values))
1000 loops, best of 3: 231 µs per loop
您可以使用 business["categories"].str.join('')
试试运气,但我猜测 Pandas 使用 Pythons 字符串函数。我怀疑你能做得比 Python 已经提供给你的更好。
我用了"".join(business["categories"])
它比business["categories"].str.join('')
快很多,但仍然比itertools.chain
方法慢4倍。我更喜欢它,因为它更具可读性并且不需要导入。
是否有 pandas 系列的 reduce
类似物?
例如,map
的类似物是 pd.Series.apply,但我找不到 reduce
的任何类似物。
我的应用是,我有一个pandas系列列表:
>>> business["categories"].head()
0 ['Doctors', 'Health & Medical']
1 ['Nightlife']
2 ['Active Life', 'Mini Golf', 'Golf']
3 ['Shopping', 'Home Services', 'Internet Servic...
4 ['Bars', 'American (New)', 'Nightlife', 'Loung...
Name: categories, dtype: object
我想使用 reduce
将列表系列合并在一起,如下所示:
categories = reduce(lambda l1, l2: l1 + l2, categories)
但这需要很长时间,因为将两个列表合并在一起是 O(n)
时间 Python。我希望 pd.Series
有一种矢量化的方式来更快地执行此操作。
在值
上有itertools.chain()
这可能会更快:
from itertools import chain
categories = list(chain.from_iterable(categories.values))
性能
from functools import reduce
from itertools import chain
categories = pd.Series([['a', 'b'], ['c', 'd', 'e']] * 1000)
%timeit list(chain.from_iterable(categories.values))
1000 loops, best of 3: 231 µs per loop
%timeit list(chain(*categories.values.flat))
1000 loops, best of 3: 237 µs per loop
%timeit reduce(lambda l1, l2: l1 + l2, categories)
100 loops, best of 3: 15.8 ms per loop
对于此数据集,chain
ing 速度大约快 68 倍。
向量化?
当你有原生的 NumPy 数据类型时,向量化就起作用了(pandas毕竟它的数据使用 NumPy)。由于我们已经在 Series 中有列表并且想要一个列表作为结果,因此矢量化不太可能加快速度。标准 Python 对象和 pandas/NumPy 数据类型之间的转换可能会耗尽您从矢量化中获得的所有性能。我曾尝试在另一个答案中对算法进行矢量化。
矢量化但速度慢
你可以使用 NumPy 的 concatenate
:
import numpy as np
list(np.concatenate(categories.values))
性能
但是我们已经有了列表,即 Python 个对象。因此矢量化必须在 Python 对象和 NumPy 数据类型之间来回切换。这让事情变慢:
categories = pd.Series([['a', 'b'], ['c', 'd', 'e']] * 1000)
%timeit list(np.concatenate(categories.values))
100 loops, best of 3: 7.66 ms per loop
%timeit np.concatenate(categories.values)
100 loops, best of 3: 5.33 ms per loop
%timeit list(chain.from_iterable(categories.values))
1000 loops, best of 3: 231 µs per loop
您可以使用 business["categories"].str.join('')
试试运气,但我猜测 Pandas 使用 Pythons 字符串函数。我怀疑你能做得比 Python 已经提供给你的更好。
我用了"".join(business["categories"])
它比business["categories"].str.join('')
快很多,但仍然比itertools.chain
方法慢4倍。我更喜欢它,因为它更具可读性并且不需要导入。