用字典有效地替换熊猫系列中的值

用字典有效地替换熊猫系列中的值

如何替换Pandas系列中的值s通过字典d已经被问了很多次了。

推荐的方法(1234)要么使用s.replace(d)或者偶尔使用s.map(d)如果您的所有系列值都在字典键中找到。

但是,性能使用s.replace通常是不合理的慢,通常比一个简单的列表理解慢5-10倍。

另一种选择,s.map(d)有很好的性能,但只有在字典中找到所有键时才推荐。

为什么s.replace那么慢,怎么才能提高性能呢?

import pandas as pd, numpy as np

df = pd.DataFrame({'A': np.random.randint(0, 1000, 1000000)})lst = df['A'].values.tolist()##### TEST 1 #####d = {i: i+1 for i in range(1000)}%timeit df['A'].replace(d)                          # 1.98s%timeit [d[i] for i in lst]                         # 134ms##### TEST 2 #####d = {i: i+1 for i in range(10)}%timeit df['A'].replace(d)                          # 20.1ms%timeit [d.get(i, i) for i in lst]                  # 243ms

注:此问题不被标记为重复,因为它正在寻找关于何时使用不同的方法给出了不同的数据集。这在回答中是明确的,也是通常在其他问题中不涉及的一个方面。


浮云间
浏览 351回答 1
1回答

智慧大石

一个简单的解决方案是选择一个方法,它依赖于字典键覆盖的完全值的估计。一般情况使用df['A'].map(d)如果映射的所有值;或使用df['A'].map(d).fillna(df['A']).astype(int)如果>5%的值映射。极少数,如<5%,d值使用df['A'].replace(d)5%的“交叉点”是特定于以下标杆的。有趣的是,简单的列表理解通常表现不佳。map在这两种情况下。标杆import&nbsp;pandas&nbsp;as&nbsp;pd,&nbsp;numpy&nbsp;as&nbsp;np df&nbsp;=&nbsp;pd.DataFrame({'A':&nbsp;np.random.randint(0,&nbsp;1000,&nbsp;1000000)})lst&nbsp;=&nbsp;df['A'].values.tolist()#####&nbsp;TEST&nbsp;1&nbsp;-&nbsp;Full&nbsp;Map&nbsp;#####d&nbsp;=&nbsp;{i:&nbsp;i+1&nbsp;for&nbsp;i&nbsp;in&nbsp;range(1000)}%timeit&nbsp;df['A'].replace(d)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;1.98s%timeit&nbsp;df['A'].map(d)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;84.3ms%timeit&nbsp;[d[i]&nbsp;for&nbsp;i&nbsp;in&nbsp;lst]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;134ms#####&nbsp;TEST&nbsp;2&nbsp;-&nbsp;Partial&nbsp;Map&nbsp;#####d&nbsp;=&nbsp;{i:&nbsp;i+1&nbsp;for&nbsp;i&nbsp;in&nbsp;range(10)}%timeit&nbsp;df['A'].replace(d)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;20.1ms%timeit&nbsp;df['A'].map(d).fillna(df['A']).astype(int)&nbsp;&nbsp;#&nbsp;111ms%timeit&nbsp;[d.get(i,&nbsp;i)&nbsp;for&nbsp;i&nbsp;in&nbsp;lst]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;243ms解释为什么s.replace它的速度太慢了,它所做的不仅仅是简单地映射一本字典。它处理一些边缘案件和可以说是罕见的情况,这通常值得更多的照顾在任何情况下。这是一段摘录replace()在……里面pandas\generic.py.items&nbsp;=&nbsp;list(compat.iteritems(to_replace))keys,&nbsp;values&nbsp;=&nbsp;zip(*items)are_mappings&nbsp;=&nbsp;[is_dict_like(v)&nbsp;for&nbsp;v&nbsp;in&nbsp;values]if&nbsp;any(are_mappings): &nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;handling&nbsp;of&nbsp;nested&nbsp;dictionarieselse: &nbsp;&nbsp;&nbsp;&nbsp;to_replace,&nbsp;value&nbsp;=&nbsp;keys,&nbsp;valuesreturn&nbsp;self.replace(to_replace,&nbsp;value,&nbsp;inplace=inplace, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;limit=limit,&nbsp;regex=regex)似乎涉及许多步骤:将字典转换为列表。遍历列表并检查嵌套字典。将关键字和值的迭代器输入替换函数。这可以与更精简的代码进行比较。map()在……里面pandas\series.py:if&nbsp;isinstance(arg,&nbsp;(dict,&nbsp;Series)): &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;isinstance(arg,&nbsp;dict): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arg&nbsp;=&nbsp;self._constructor(arg,&nbsp;index=arg.keys()) &nbsp;&nbsp;&nbsp;&nbsp;indexer&nbsp;=&nbsp;arg.index.get_indexer(values) &nbsp;&nbsp;&nbsp;&nbsp;new_values&nbsp;=&nbsp;algos.take_1d(arg._values,&nbsp;indexer)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python