python报错—使用.str.contains()方法替换某一列报错:AttributeError: ‘str‘ object has no attribute ‘str‘及解决方案

项目场景:

1.要求:筛选channel_type_desc列,将"含有实体渠道的"全部替换"实体渠道",将"含有电子渠道的"全部替换成"电子渠道",将"含有直销渠道的"全部替换成"直销渠道",其他替换为"未识别"。

导入数据及查看数据情况

#导入数据
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_machine_learing_work\\501_model\\data\\第一次建模用的样本数据\\训练集\\v1_6_feature.csv"

data_pos_1=read_file(file_pos)

#查看channel_type_desc的数据分布
data_pos_1.channel_type_desc.value_counts() 

在这里插入图片描述


问题描述

2.实现过程

def func(x):
	if x.str.contains('实体渠道'):
		return "实体渠道"
	elif x.str.contains('电子渠道'):
		return "电子渠道"
	elif x.str.contains('直销渠道'):
		return "直销渠道"
	else:
		return "未识别"

使用apply方法对 “data_pos_1[‘channel_type_desc’]” 调用函数func。

data_pos_1[data_pos_1['channel_type_desc'].apply(func)]

3.发现问题:报错:AttributeError: ‘str’ object has no attribute ‘str’

在这里插入图片描述


原因分析:

  • 原因一:.str.contains()函数只能对Series使用。
  • 原因二:Series使用apply方法后,apply会自动遍历整个Series,将Series分解为一个个元素(元素数据类型跟数据列的数据类型一致)传入函数中,按照相对应的函数进行运算,最终将所有的计算结果存储在一个新的Series中返回。

4.具体原因分析:
在这里插入图片描述

从上面我们可以看到,“data_pos_1[‘channel_type_desc’]” 数据类型是Series,但是 “data_pos_1[data_pos_1[‘channel_type_desc’].apply(func)]” 等于对Series使用apply方法,实际上是将"data_pos_1[‘channel_type_desc’]"中的元素一个个传入到func函数中,元素类型是<class ‘str’>,又因为.str.contains()函数只能对Series使用,因此会报错AttributeError: ‘str’ object has no attribute ‘str’。

原因二举例说明:
1.创建测试DataFrame

import pandas as pd
df = pd.DataFrame({'A': [1, 80, 4],
                   'B': [9, 80, 5],
                   'C': ['pink','puple','blue']})
df                    

在这里插入图片描述

2.查看对 Series下使用 apply方法,Series传入函数的数据类型。

print(type(df['C']))

在这里插入图片描述

def test(data):
	print(data)
	print(type(data))
	print('______')
	return data

result=df['C'].apply(test)

print('------分隔线------')
print("最终返回一个新的Series")
print(type(result))
print('------分隔线------')
print("将series对象转为Dataframe对象",'\n',result.apply(pd.Series),'\n',type(result.apply(pd.Series)))

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

从上面可以看出,apply将df[‘C’]中元素一个个分解开传入函数中,每个元素类型为<class ‘str’>,最终所有元素合并成一个新的Series(result)返回。


解决方案:

方案一: 使用其他方法进行替换,不使用.str.contains()函数。

举例1:使用re.match()函数

import re 

def func(data):
    if re.match(r'[\u4e00-\u9fa5]*实体渠道*[\u4e00-\u9fa5]',str(data)):
        return "实体渠道"
    elif re.match(r'[\u4e00-\u9fa5]*电子渠道*[\u4e00-\u9fa5]',str(data)):
        return "电子渠道"
    elif re.match(r'[\u4e00-\u9fa5]*直销渠道*[\u4e00-\u9fa5]',str(data)):
        return "直销渠道"
    else:
        return "未识别"

data_pos_1['channel_type_desc']=data_pos_1['channel_type_desc'].apply(func)   

举例2:使用re.search()函数

import re

def func(x):
    if re.search(r'[\u4e00-\u9fa5]*实体渠道*[\u4e00-\u9fa5]',str(x)):
        return "实体渠道"
    elif re.search(r'[\u4e00-\u9fa5]*电子渠道*[\u4e00-\u9fa5]',str(x)):
        return "电子渠道"
    elif re.search(r'[\u4e00-\u9fa5]*直销渠道*[\u4e00-\u9fa5]',str(x)):
        return "直销渠道"
    else:
        return "未识别"
        
data_pos_1['channel_type_desc']=data_pos_1['channel_type_desc'].apply(func)   

举例3:使用np.where()函数,这个方法没有加上str.contains()模糊查询来的简洁,不太推荐。

import numpy as np 

data_pos_1['channel_type_desc']=np.where((data_pos_1['channel_type_desc']=='社会实体渠道')|(data_pos_1['channel_type_desc']=='自营实体渠道'),'实体渠道',
									np.where((data_pos_1['channel_type_desc']=='社会电子渠道')|(data_pos_1['channel_type_desc']=='自营电子渠道'),'电子渠道',
										np.where((data_pos_1['channel_type_desc']=='社会直销渠道')|(data_pos_1['channel_type_desc']=='自营直销渠道'),'直销渠道','未识别')))

举例4:使用Series.replace()函数

#第一种写法
def func(x):
    result=x.replace(r'[\u4e00-\u9fa5]*实体渠道*[\u4e00-\u9fa5]','实体渠道',regex=True)
    result1=result.replace(r'[\u4e00-\u9fa5]*电子渠道*[\u4e00-\u9fa5]','电子渠道',regex=True)
    result2=result1.replace(r'[\u4e00-\u9fa5]*直销渠道*[\u4e00-\u9fa5]','直销渠道',regex=True)
    result3=result2.replace(np.nan,'未识别',regex=True)
    return result3
  
data_pos_1['channel_type_desc']=func(data_pos_1['channel_type_desc'])   


#第二种写法
data_pos_1['channel_type_desc'].replace(r'[\u4e00-\u9fa5]*实体渠道*[\u4e00-\u9fa5]','实体渠道',regex=True).replace(r'[\u4e00-\u9fa5]*电子渠道*[\u4e00-\u9fa5]','电子渠道',regex=True).replace(r'[\u4e00-\u9fa5]*直销渠道*[\u4e00-\u9fa5]','直销渠道',regex=True).replace(np.nan,'未识别',regex=True)     

注意: 不可以使用 data_pos_1[‘channel_type_desc’].apply(func) 调用函数,会报错TypeError: str.replace() takes no keyword arguments,具体原因查看python报错—为什么用apply方法使用.replace()方法报错TypeError: str.replace() takes no keyword arguments

举例5:使用re.sub()函数

import re 
import re 

def func(data):
    result1=re.sub(r'[\u4e00-\u9fa5]*实体渠道*[\u4e00-\u9fa5]',"实体渠道",str(data))
    result2=re.sub(r'[\u4e00-\u9fa5]*电子渠道*[\u4e00-\u9fa5]',"电子渠道",result1)
    result3=re.sub(r'[\u4e00-\u9fa5]*直销渠道*[\u4e00-\u9fa5]',"直销渠道",result2)
    result4=re.sub(r'nan','未识别',result3)
    return result4
    
data_pos_1['channel_type_desc']=data_pos_1['channel_type_desc'].apply(func)   

注意: 不可以使用 data_pos_1[‘channel_type_desc’]=func(data_pos_1[‘channel_type_desc’]) 调用函数,运行结果不致,re.sub(pattern, repl, string, count=0, flags=0),第三个要被查找替换的原始字符串,必须是string字符串类型。具体参数可以参考:python基础—re模块下的函数及匹配对象的属性与方法(re.match()/re.search()…等)

方案二: 对Series数据类型使用.str.contains()方法

举例1:使用np.where()函数+.str.contains()函数

import numpy as np 

data_pos_1['channel_type_desc']=np.where(data_pos_1['channel_type_desc'].str.contains('实体渠道'),'实体渠道',
										np.where(data_pos_1['channel_type_desc'].str.contains('直销渠道'),'直销渠道',
											np.where(data_pos_1['channel_type_desc'].str.contains('电子渠道'),'电子渠道','未识别')))

参考文章:
[1].str.contains()方法官方文档
[2]pandas下的DataFrame、Series对象的apply方法
[3].str.contains()只能对Series使用

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个错误通常是因为字符串类型没有contains属性导致的。contains是pandas中Series和DataFrame对象的方法,用于检查字符串是否包含指定的子字符串。如果您在字符串上使用这个方法,会出现这个错误。 要解决这个问题,您需要将字符串转换为pandas中的Series或DataFrame对象,然后再使用contains方法。如果您只是想检查一个字符串是否包含另一个字符串,可以使用Python中的in关键字。 例如,以下是使用contains方法检查DataFrame中的一个列是否包含指定子字符串的示例代码: ``` import pandas as pd df = pd.DataFrame({'column1': ['foo', 'bar', 'baz']}) # 检查列中是否包含指定的子字符串 df['column1_contains_foo'] = df['column1'].str.contains('foo') ``` 如果您只是想检查一个字符串是否包含另一个字符串,可以使用以下代码: ``` s = 'Hello, world!' # 检查字符串是否包含指定子字符串 if 'world' in s: print('Found it!') ``` ### 回答2: 属性错误:'str'对象没有'contains'属性。这个错误通常出现在尝试在一个字符串对象上使用'contains'函数时。 在Python中,'contains'函数是Pandas库中Series对象的一个方法,用于检查字符串是否包含指定的子字符串。但是,在普通的字符串对象上是没有'contains'属性的。 要解决这个错误,有几种可能的方法: 1. 检查语句中的对象:首先,确保你正在使用一个Series对象,而不是一个普通的字符串对象。你可以通过使用Pandas的Series函数将字符串转换为Series对象,然后再使用'contains'方法。 2. 使用'in'关键字判断子字符串是否包含在字符串中:如果你只是想检查一个字符串是否包含另一个子字符串,你可以使用'in'关键字来替代'contains'函数。例如,你可以使用以下语句:```if "子字符串" in my_string:``` 3. 更新Python或Pandas库:如果你使用的是较旧版本的Python或Pandas库,可以尝试更新它们到最新版本,以确保你能够使用最新的函数和方法。 无论如何,要解决这个错误,你需要确认你使用的对象以及你尝试调用的方法是否匹配,并根据情况选择适当的方法来检查字符串是否包含指定的子字符串。 ### 回答3: AttributeError: 'str' object has no attribute 'contains' 意味着在字符串对象上使用了"contains"属性,但是字符串对象没有这个属性。更具体地说,这个错误通常发生在尝试将字符串对象视为容器对象并使用contains()方法检查字符串是否包含某个特定元素时。 在Python中,contains()方法不适用于字符串对象。如果想检查一个字符串是否包含另一个字符串,可以使用in关键字来判断。 例如,如果我们有一个字符串对象str1和一个字符串"example",我们可以通过以下方式检查字符串是否包含在另一个字符串中: ```python str1 = "This is an example string" if "example" in str1: print("字符串包含'example'") else: print("字符串不包含'example'") ``` 以上代码将输出"字符串包含'example'",因为"example"字符串包含在str1中。 总结起来,AttributeError: 'str' object has no attribute 'contains'错误说明在字符串对象上使用contains()方法,但是字符串对象并没有这个属性。正确的方式是使用in关键字来检查字符串是否包含某个子字符串。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值