为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

浮云间 2019-06-26 14:46:56
用字典有效地替换熊猫系列中的值如何替换Pandas系列中的值s通过字典d已经被问了很多次了。推荐的方法(1, 2, 3, 4)要么使用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注:此问题不被标记为重复,因为它正在寻找关于何时使用不同的方法给出了不同的数据集。这在回答中是明确的,也是通常在其他问题中不涉及的一个方面。
查看完整描述

1 回答

?
智慧大石

TA贡献1946条经验 获得超3个赞

一个简单的解决方案是选择一个方法,它依赖于字典键覆盖的完全值的估计。

一般情况

  • 使用

    df['A'].map(d)

    如果映射的所有值;或
  • 使用

    df['A'].map(d).fillna(df['A']).astype(int)

    如果>5%的值映射。

极少数,如<5%,d值

  • 使用

    df['A'].replace(d)

5%的“交叉点”是特定于以下标杆的。

有趣的是,简单的列表理解通常表现不佳。map在这两种情况下。

标杆

import pandas as pd, numpy as np

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

解释

为什么s.replace它的速度太慢了,它所做的不仅仅是简单地映射一本字典。它处理一些边缘案件和可以说是罕见的情况,这通常值得更多的照顾在任何情况下。

这是一段摘录replace()在……里面pandas\generic.py.

items = list(compat.iteritems(to_replace))keys, values = zip(*items)are_mappings = [is_dict_like(v) for v in values]if any(are_mappings):
    # handling of nested dictionarieselse:
    to_replace, value = keys, valuesreturn self.replace(to_replace, value, inplace=inplace,
                    limit=limit, regex=regex)

似乎涉及许多步骤:

  • 将字典转换为列表。
  • 遍历列表并检查嵌套字典。
  • 将关键字和值的迭代器输入替换函数。

这可以与更精简的代码进行比较。map()在……里面pandas\series.py:

if isinstance(arg, (dict, Series)):
    if isinstance(arg, dict):
        arg = self._constructor(arg, index=arg.keys())

    indexer = arg.index.get_indexer(values)
    new_values = algos.take_1d(arg._values, indexer)


查看完整回答
反对 回复 2019-06-26
  • 1 回答
  • 0 关注
  • 350 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信