【问题标题】:Pandas how can 'replace' work after 'loc'?Pandas 如何在“loc”之后“替换”工作?
【发布时间】:2018-06-27 03:39:20
【问题描述】:

我已经尝试了很多次,但是在使用 'loc' 后,'replace' 似乎无法正常工作。 例如,我想将 'conlumn_b' 替换为 'conlumn_a' 值为 'apple' 的行的正则表达式。

这是我的示例代码:

df.loc[df['conlumn_a'] == 'apple', 'conlumn_b'].replace(r'^11*', 'XXX',inplace=True, regex=True)

例子:

conlumn_a       conlumn_b
apple           123
banana          11
apple           11
orange          33

我对“df”的预期结果是:

conlumn_a       conlumn_b
apple           123
banana          11
apple           XXX
orange          33

有人遇到过需要在 'loc' 之后用正则表达式 'replace' 的问题吗?

或者你们还有其他好的解决方案吗?

非常感谢您的帮助!

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    inplace=True 作用于它被应用的对象

    当您调用.loc 时,您正在对数据框对象进行切片以返回一个 对象。

    >>> id(df)
    4587248608
    

    还有,

    >>> id(df.loc[df['conlumn_a'] == 'apple', 'conlumn_b'])
    4767716968
    

    现在,在这个新切片上调用就地replace 将应用替换操作,更新新切片本身,而不是原始切片。


    现在,请注意您在 int 的列上调用 replace,但不会发生任何事情,因为正则表达式适用于字符串。

    以下是我为您提供的解决方法。根本不要使用正则表达式。

    m = df['conlumn_a'] == 'apple'
    df.loc[m, 'conlumn_b'] = df.loc[m, 'conlumn_b'].replace(11, 'XXX')
    
    df
    
      conlumn_a conlumn_b
    0     apple       123
    1    banana        11
    2     apple       XXX
    3    orange        33
    

    或者,如果您需要基于正则表达式的替换,那么 -

    df.loc[m, 'conlumn_b'] = df.loc[m, 'conlumn_b']\
               .astype(str).replace('^11$', 'XXX', regex=True)
    

    不过,这会将您的列转换为对象列。

    【讨论】:

    • 谢谢,我会采纳你的建议。情况是我在“替换”中需要正则表达式,“11 to XXX”只是一个示例,实际的正则表达式可能更复杂。@cᴏʟᴅsᴘᴇᴇᴅ
    • 感谢您解释问题的原因:我不知道 loc 正在创建一个新对象。了解根本原因总是好的。
    【解决方案2】:

    我要向recent answer of mine 借钱。这种技术是用于更新数据帧的通用策略:

    df.update(
        df.loc[df['conlumn_a'] == 'apple', 'conlumn_b']
          .replace(r'^11$', 'XXX', regex=True)
    )
    
    df
    
      conlumn_a conlumn_b
    0     apple       123
    1    banana        11
    2     apple       XXX
    3    orange        33
    

    请注意,我所做的只是删除了 inplace=True,而是将其包装在 pd.DataFrame.update 方法中。

    【讨论】:

    • @piRSquared - 为什么update 更好?它更快吗?还是只有更好的代码?
    • 更好的代码。将其用于预期目的。我展示了应该如何使用它来完成人们使用 inplace=True 想要完成的事情,但因为他们在后续对象上执行它而无法完成。
    • 这实际上是更好的代码,但遗憾的是,它与.loc 替代方案相比完全没有性能。刚刚在 2M 行上尝试过,它在不到一分钟的时间内没有运行,不得不停止它。与此同时,“脏”.loc 替代方案会立即运行
    【解决方案3】:

    我认为你需要在双方过滤:

    m = df['conlumn_a'] == 'apple'
    df.loc[m,'conlumn_b'] = df.loc[m,'conlumn_b'].astype(str).replace(r'^(11+)','XXX',regex=True)
    print (df)
      conlumn_a conlumn_b
    0     apple       123
    1    banana        11
    2     apple       XXX
    3    orange        33
    

    【讨论】:

    • 但是我和你一样担心“更新”:它是否更快。我想我将对此进行测试。
    • @JonathanZhou - 最好的测试它,但在我看来它更慢。
    • @jezrael 你知道为什么df[df[col1=='aa']][col2] = df[df[col1=='aa']][col2].replace(map_dict) 不起作用吗?
    • @mingchau - 问题出在链式索引上,检查this - 它只是替换过滤的系列,而不是 DataFrame 切片
    猜你喜欢
    • 1970-01-01
    • 2020-07-28
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    相关资源
    最近更新 更多