python替换—Series.replace()与Series.str.replace()的区别及为何replace()无效的解决方法


前言

在Pandas中做数据处理,经常使用.replace()与.str.replace()方法来进行数据替换,本文介绍两种方法适用的对象,其中对于Series数据类型,它是一个由一维数组表示的DataFrame列,而.replace和.str.replace是Series对象的两种方法,虽然它们的名称相似,并且都用于替换Series的值,但实际上它们之间存在不同之外。


一、.replace()函数

str.replace()方法

函数语法:

str.replace(old,new,count)

参数说明:

参数描述
old不可省略参数,string,被替换的字符串
new不可省略参数,string,替换后的字符串
count可选参数,int,替换不超过max次。

举例1: 省略count时,匹配到的所有old字符串都会被替换成new字符串。

testStr = 'visit CSDN website'

#省略count时,匹配到的所有old字符串都会被替换成new字符串。
result = testStr.replace('website','!')
print('String after replacing:', result)

运行结果:
在这里插入图片描述
举例2: count值出现几次即代表replace()替换字符串的次数

testStr = 'visit CSDN website website website'

#count=2时,replace替换2次
result = testStr.replace('website','!',2)
print('String after replacing:', result)

#当count大于old字符串出现次数,即全部替换,此时count参数出现没有任何意义。

运行结果:

在这里插入图片描述

testStr = 'visit CSDN website website website'

#当count为负数,count参数不作用。replace()方法将全部old_str替换为new_str。
result = testStr.replace('website','!',-1)
print('String after replacing:', result)

运行结果:
在这里插入图片描述

DataFrame.replace()方法/Series.replace()方法

DataFrame.replace()函数语法:

DataFrame.replace(to_replace=None, value=_NoDefault.no_default, *,inplace=False, limit=None, regex=False, method=_NoDefault.no_default)

Series.replace()函数语法:

Series.replace(to_replace=None, value=_NoDefault.no_default, *,inplace=False, limit=None, regex=False, method=_NoDefault.no_default)

在Pandas中,Series是一个由一维数组表示的DataFrame列。Series.replace()与DataFrame.replace()方法参数一致。而Series对象的有.replace()和.str.replace()两种方法。虽然它们的名称相似,并且都用于替换Series的值,但实际上它们之间存在不同之外,下面会讲到。

参数说明:

参数描述说明
to_replace被替换的值字符串、正则表达式、str,正则表达式,数字的列表、字典,默认无。
value替换后的值标量、字典、列表、str、正则表达式、默认无。
inplace是否要改变原数据布尔值,默认是False,False是不改变,True是改变。
limit控制填充次数。整数,默认无。
regex是否使用正则,False是不使用,True是使用,默认是False。是否翻译to_replace和/或value作为正则表达式。如果这是True然后to_replace必须成为一个字符串。或者,这可以是一个正则表达式或一个列表、字典或正则表达式数组,在这种情况下to_replace一定是None。
method填充方式,pad,ffill,bfill分别是向前,向前,向后填充。当to_replace 是标量、列表或元组且 value 是 None 时,默认使用的替换方法为pad。

举例1: 对DataFrame进行替换。

import pandas as pd
data = pd.DataFrame({'A': [1, 80, 4],
                     'B': [9, 80, 5],
                     'C': ['foo','another foo bar','baz']})
print("data:\n", data)
print("data.dtypes:\n", data.dtypes)

#用dict进行单值、多值填充
data.replace({1,80},{'a','b'}) #1被a替换,80被b替换。
data.replace({1:'a',9:'b'}) #另一种写法,1被a替换,9被b替换。推荐这种写法。

data.replace({'A':1,'B':9},100) #A列的1与B列的9都被替换为100。
data.replace({'A':{1:10, 4:40}}) #A列的1被替换为10,4被替换为40。

#用list进行单值、多值填充
data.replace([1,9],'b')  #1,9都被b替换。
data.replace([1,9],[2,10]) #1,9分别被2,10替换。

#替换全部
data.replace(80,8)

#某一列或者某几列
data['B'].replace(9,20) #将B列中的9替换成20。
data[['A','B']].replace(80,8) #将A、B列中的9替换成20。

#某一行或者某几行
data.iloc[1].replace(80,8) #第二行的80替换成8。
data.iloc[0:2].replace(80,8) #第一、二行的80替换成8。

#to_replace是正则表达式,regex=True
data.replace(r'fo.$','new',regex=True)
data.replace({'C':r'fo.$'}, {'C':'new'}, regex=True)

#如果regex一个正则表达式或一个列表、字典或正则表达式数组,在这种情况下to_replace一定是None。
data.replace(regex=r'fo.$', value='new')
data.replace(regex={r'fo.$':'new', 'baz':'abc'})
data.replace(regex=[r'fo.$','baz'], value='new')

#inplace=True,改变原数据
data.replace(80,8,inplace=True)
data.iloc[0:2].replace(80,8,inplace=True)

#当to_replace是标量、列表或元组且value是 None 时,methond默认使用的替换方法为pad。
data.replace(['foo','baz'])

举例2: 对Series进行替换。

import pandas as pd
data = pd.DataFrame({'A': [1, 80, 4],
                     'B': [9, 80, 5],
                     'C': ['foo','another foo bar','baz']})
print("data:\n", data)
print("data.dtypes:\n", data.dtypes)

#用dict进行单值、多值填充
data['C'].replace({'foo':'hello'}) #将C列中的foo替换成hello。
data['C'].replace({'foo':'hello','baz':'bus'}) #将C列中的foo替换成hello,baz替换成bus。

#用list进行单值、多值填充
data['C'].replace(['foo'],['baz'])#将C列中的foo替换成baz。
data['C'].replace(['foo','baz'],'b'))#将C列中的foo和baz替换成b。
data['C'].replace(['foo','baz'],['hello','bus']) #将C列中的foo替换成baz,baz替换成bus。

#某一列或者某几列
data['B'].replace(9,20) #将B列中的9替换成20。

#某一行或者某几行
data.iloc[1].replace(80,8) #第二行的80替换成8。

#to_replace是正则表达式,regex=True
data['C'].replace(r'fo.$','new',regex=True)
data['C'].replace({r'fo.$':'new'}, regex=True)

#如果regex一个正则表达式或一个列表、字典或正则表达式数组,在这种情况下to_replace一定是None。
data['C'].replace(regex=r'fo.$', value='new')
data['C'].replace(regex={r'fo.$':'new', 'baz':'abc'})
data['C'].replace(regex=[r'fo.$','baz'], value='new')

#inplace=True,改变原数据
data['B'].replace(9,8,inplace=True)
data.iloc[1].replace(80,8,inplace=True)

#当to_replace是标量、列表或元组且value是 None 时,methond默认使用的替换方法为pad。
data['C'].replace(['foo','baz'])#将C列中的foo替换成hello。

二、.str.replace()方法

Series.str.replace()方法

函数语法:

Series.str.replace(pat, repl,n=-1,case=None,flags=0,regex=None)

参数说明:

参数描述
pat要查找的字符串,string,不可省略的参数。
repl替换的字符串,string,可以调用函数,不可省略的参数。
n要进行替换的次数,默认全部。
case是否区分大小写。
flagsre模块中的标志。如re.IGNORECASE。
regex是否设置为正则表达式,False是不使用,True是使用,默认是True。

.str.replace() 仅用于字符串匹配和替换,接受两个参数,第一个参数指定要替换的模式,仅限于正则表达式,第二个参数指定要用于替换的字符串。

举例:

import pandas as pd
data = pd.DataFrame({'A': ['1', '2', '4'],
                     'B': ['2023/9/9', '2023/8/8','2023/5/4'],
                     'C': ['FOO','ANOther foo bar','BAZ']})
print("data:\n", data)
print("data.dtypes:\n", data.dtypes)

#普通替换
data['C'].str.replace('FOO','foo') #将C列中FOO替换成foo。

#正则表达式的替换
data['B'].str.replace('[/]','-')

#预编译好的正则表达式替换
import pandas as pd 
import re 
pat=re.compile('[/]')
data['B'].str.replace(pat,'-')

#函数替换
data['C'].str.replace('[A-Z]',lambda x:x.group().lower()) #将C列中大写字母替换成小写字母。

三、.replace()与.str.replace() 使用方法的区别

1、.replace()方法可以用于数字、布尔值和任何可替换的数据类型;而.str.replace()方法仅适用于字符串。

创建测试DataFrame,下面的例子都基于这个DataFrame。

import pandas as pd
data = pd.DataFrame({'A': ['1', '2', '4'],
                     'B': [9, 80, 5],
                     'C': ['FOO','ANOther foo bar','BAZ']})
print("data:\n", data)
print("data.dtypes:\n", data.dtypes)

运行结果:
在这里插入图片描述

举例1: .replace()方法作用于int64数据类型。

要求:将整个dataframe中数据列B的9替换成20。

data['B'].replace(9,20)

运行结果:
在这里插入图片描述

举例2: .str.replace()方法作用于int64数据类型,报错:AttributeError: Can only use .str accessor with string values!。

要求:将整个dataframe中数据列B的9替换成20

data['B'].str.replace(9,20)

运行结果:

在这里插入图片描述

我们可以看数据列B是int64数据类型,因此直接使用str.replace() 会报以下错误提示,因为 .str.replace()只针对字符串数据类型 的列有效。

2、.replace()方法可以一次为单个字符串元素(str)、一列(Series)、多个列(DataFrame)工作,如果有需要,可以对整个DataFrame的值进行替换;而.str.serires()方法只能作用于一列(Series)。

创建测试DataFrame,下面的例子都基于这个DataFrame。

import pandas as pd
data = pd.DataFrame({'A': [9, 20, 40],
                     'B': [9, 80,5],
                     'C': ['foo','another foo bar','baz']})
print("data:\n", data)
print("data.dtypes:\n", data.dtypes)

运行结果:
在这里插入图片描述

举例1: .replace()方法作用于整个DataFrame的值。

要求:将C列中的foo替换成hello,A、B列中9替换成bus。

data.replace({'foo':'hello',9:'bus'}) #将C列中的foo替换成hello,A、B列中9替换成bus。

运行结果:
在这里插入图片描述

要求:将整个dataframe中的9替换成90。

data.replace(9,90) #将整个dataframe中的9替换成90

运行结果:

在这里插入图片描述

举例2: .replace()方法作用于单个字符串元素(<class ‘str’>),实际上是函数str.replace(old,new,count)。

要求:将C列中第二行元素从80替换成8。

print(type(data['C'].loc[0]))

data['C'].loc[0].replace('foo','abc')

运行结果:
在这里插入图片描述

举例3: .replace()方法作用于多列。

要求:将A、B列中的80替换成8。

data[['A','B']].replace(80,8) 

运行结果:

在这里插入图片描述

举例4: .str.relace()方法作用于整个dataframe、多列、单个字符串元素(<class ‘str’>),都会报错。

要求:将整个dataframe中的9替换成90

data.str.replace('9','90')

报错:
在这里插入图片描述

要求:将A、B列中的80替换成8。

data[['A','B']].str.replace(80,8) 

报错:
在这里插入图片描述

要求:将C列中第二行元素从80替换成8。

data['C'].loc[0].str.replace('foo','abc')

报错:
在这里插入图片描述

3、.replace()方法可以一次执行多个独立的替换,.str.replace()方法一次只可以替换一件事。

创建测试DataFrame,下面的例子都基于这个DataFrame。

import pandas as pd
data = pd.DataFrame({'A': ['9', '20', '40'],
                     'B': ['9', '80','5'],
                     'C': ['foo','another foo bar','baz']})
print("data:\n", data)
print("data.dtypes:\n", data.dtypes)

运行结果:
在这里插入图片描述

举例1: .replace()方法执行多个独立的替换。

要求:将整个dataframe中的数据列C中foo替换成text1,bar替换成text2。

#更好的表达方式
data['C'].replace({'foo': 'text1', 'bar': 'text2'}, regex=True)

data['C'].replace('foo','text1',regex=True).replace('bar','text2'), regex=True)

运行结果:
在这里插入图片描述

举例2: .str.replace()方法只一个一个替换,不可以像.replace()方法一样传入字典做多个独立的替换。

要求:将整个dataframe中的数据列C中foo替换成text1,bar替换成text2。

data['C'].str.replace('foo','text1').str.replace('bar','text2')

运行结果:
在这里插入图片描述

4、.replace()方法是默认regex=False,.str.replace()方法是默认启用正则表达式替换。

  • 两者方法默认行为的差异:
    • 子字符串替换,.replace() 方法默认情况下只会执行全字匹配,.str.replace()方法将替换每次出现的子字符串
    • 正则表达式替换,.replace()方法除非您指定 regex=True,否则与将第一个参数解释为正则表达式的.str.replace()方法恰恰相反。注意: .replace()方法的regex=True只有在进行字符串替换才有效,例如data.replace({‘foo’:‘hello’,9:-3}, regex=True)是无效的。

创建测试DataFrame,下面的例子都基于这个DataFrame。

import pandas as pd
data = pd.DataFrame({'A': [9, 20, 40],
                     'B': [9, 80,5],
                     'C': ['foo','another foo bar','baz']})
print("data:\n", data)
print("data.dtypes:\n", data.dtypes)

运行结果:
在这里插入图片描述

举例1

要求:将字符串foo全部替换字符串text1。

data['C'].replace('foo','text1') #默认情况下,只会执行对foo全字匹配替换。
data['C'].replace('foo','text1',regex=True) #regex=True情况下,每次出现的子字符串foo都会被替换为text1。
data['C'].str.replace('foo','text1') #默认情况下,每次出现的子字符串foo都会被替换为text1。

运行结果1:
在这里插入图片描述
运行结果2:
在这里插入图片描述
运行结果3:

在这里插入图片描述


四、常见的坑

python中.replace()方法不起作用

导入数据及查看数据情况

import os
import pandas as pd 
import numpy as np
#读取文件
def read_file(filepath):
    os.chdir(os.path.dirname(filepath))
    return pd.read_csv(os.path.basename(filepath),encoding='utf-8')
file_pos="F:\\python_test\\data_1.csv"
data_pos=read_file(file_pos)
data_pos

在这里插入图片描述

data_pos.dtypes

在这里插入图片描述

1、要求: 将2021金额与2022金额的 ¥ 与 , 这两个符号替换为空。

2、实现过程:

def convert_currency(value):
	'''
	移除不是数字字符 ¥,
	'''
	new_value=value.replace({',':'','¥':''})
	return new_value

#调用函数
a=convert_currency(data_pos['2021金额'])
a

运行结果:
在这里插入图片描述
3、发现问题: 使用.replace()无效, 将2021金额与2022金额的 ¥ 与 , 这两个符号并没有替换为空。

4、原因分析: .replace()方法默认情况下只会执行全字匹配,只有regex=True在进行正则表达式替换。

5、解决方案:

  • 方案一:使用.replace(,regex=True),使得to_replace是正则匹配。
def convert_currency(value):
	'''
	移除不是数字字符 ¥,
	'''
	new_value=value.replace({',':'','¥':''},regex=True)
	return new_value

#调用函数
a=convert_currency(data_pos['2021金额'])
a

运行结果:
在这里插入图片描述

注意: 针对上面的解决方案一使用apply调用函数会报错:TypeError: str.replace() takes no keyword arguments。

如下代码

data_pos['2021金额'].apply(convert_currency)

在这里插入图片描述
原因: Series使用apply方法后,apply会自动遍历整个Series,将Series分解为一个个元素(元素数据类型跟数据列的数据类型一致)传入函数中。因为data_pos[‘2021金额’]是Series数据类型,apply调用convert_currency()函数,实际上将一个个单独的<class ‘str’>元素调用.replace()方法,会默认为str.replace(old,new,count),并不存在regex这个参数,因此会报错:TypeError: str.replace() takes no keyword arguments。具体分析过程可参考:python报错—为什么用apply方法使用.replace()方法报错TypeError: str.replace() takes no keyword arguments

  • 方案二:使用.str.replace(),默认为pat是正则匹配。
def convert_currency(value):
	'''
	移除不是数字字符 ¥,
	'''
	new_value=value.str.replace(',','').str.replace('¥','')
	return new_value

#调用函数
a=convert_currency(data_pos['2021金额'])
a

运行结果:
在这里插入图片描述

注意: 针对上面的解决方案二使用apply调用函数会报错:AttributeError: ‘str’ object has no attribute ‘str’。

如下代码

data_pos['2021金额'].apply(convert_currency)

原因: Series使用apply方法后,apply会自动遍历整个Series,将Series分解为一个个元素(元素数据类型跟数据列的数据类型一致)传入函数中。对于使用.str.replace()方法来进行正则替换,.str.replace()只适用于Series对象,不用作用于<class ‘str’>类型,因此会报错AttributeError: ‘str’ object has no attribute ‘str’。具体分析过程可参考:python报错—为什么用apply方法使用.replace()方法报错TypeError: str.replace() takes no keyword arguments


参考文章:

https://blog.csdn.net/m0_62011685/article/details/124716966?ydreferer=aHR0cHM6Ly9jbi5iaW5nLmNvbS8%3D
https://www.cnblogs.com/cgmcoding/p/13362539.html
https://www.coder.work/article/1269173
https://geek-docs.com/pandas/pandas-questions/419_pandas_what_is_the_difference_between_seriesreplace_and_seriesstrreplace.html
https://zhuanlan.zhihu.com/p/108861452
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.replace.html
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.replace.html#pandas.DataFrame.replace
https://vimsky.com/examples/usage/python-pandas.Series.replace.html

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值