Pandas SettingWithCopyWarning及Too many indexers错误解决求助
问题:Pandas SettingWithCopyWarning及.loc索引错误解决
发送请求抓取网页文本时遇到以下警告,尝试使用.copy()无效,改用_df.loc时又触发too many indexers错误:
SettingWithCopyWarning:
A value is trying to be set on a copy of a
slice from a DataFrameSee the caveats in the documentation:
https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy _df['text']=remove_one_words_from_list(website_text,_df['language']).copy()
注:调用get_the_text2方法时,每次传入DataFrame的一行数据。
相关代码
def get_the_text2(_df): ''' 第二次用不同方法发送请求,获取文章文本 参数 ---------- _df : DataFrame 返回 ------- URL对应的文本内容 ''' df['text']='' # for k,i in enumerate(_df['url']): if str(_df): website_text=list() print(_df) #time.sleep(2) try: response=requests.get(_df['url'],headers={"User-Agent" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}) status_code=response.status_code soup = BeautifulSoup(response.content, 'html.parser') if len(website_text)<=10: website_text=list() if soup.article: if soup.article.find_all(['p',re.compile("^h\d{1}")]): for data in soup.article.find_all(['p',re.compile("^h\d{1}")]): website_text.append(data.get_text(strip=True)) #df.at[k,'text']=remove_one_words_from_list(website_text,df.at[k,'language']) _df['text']=remove_one_words_from_list(website_text,_df['language']).copy() print('****ARTICLE P & H{1}****',remove_one_words_from_list(website_text,_df['language'])) for _index,item in enumerate(df['status_code']): if item !=200: get_the_text2(df.loc[_index])
编辑1:.loc索引报错信息
使用以下代码时:
_df['text']=remove_one_words_from_list(website_text,_df.loc[:,'language']).copy()
触发报错:
IndexingError Traceback (most recent call last) Cell In[14], line 102 100 for _index,item in enumerate(df['status_code']): 101 if item !=200: --> 102 get_the_text2(df.loc[_index]) File c:\Users\\anaconda3\envs\GDELT\Lib\site-packages\pandas\core\indexing.py:939, in _LocationIndexer._validate_key_length(self, key) 937 raise IndexingError(_one_ellipsis_message) 938 return self._validate_key_length(key) --> 939 raise IndexingError("Too many indexers") 940 return key IndexingError: Too many indexers
编辑2:.loc['language']无报错但警告仍存在
改用以下代码后无索引错误,但SettingWithCopyWarning依旧:
_df['text']=remove_one_words_from_list(website_text,_df.loc['language']).copy()
已知问题根源,但不清楚具体修复方法。
解决方案
问题本质:传入
get_the_text2的df.loc[_index]是Series对象,不是DataFrame。直接对Series赋值会触发视图/副本歧义警告;而_df.loc[:,'language']是给Series用了二维索引语法,因此报错。修复代码示例:
def get_the_text2(df, idx): ''' 第二次用不同方法发送请求,获取文章文本并更新到原DataFrame 参数 ---------- df : DataFrame 原数据集 idx : int 需要处理的行索引 ''' url = df.loc[idx, 'url'] language = df.loc[idx, 'language'] website_text = [] try: response = requests.get(url, headers={"User-Agent" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}) soup = BeautifulSoup(response.content, 'html.parser') if soup.article: # 提取所有p和h标签文本 for data in soup.article.find_all(['p', re.compile("^h\d{1}")]): website_text.append(data.get_text(strip=True)) # 用.at精准赋值,彻底避免视图/副本问题 processed_text = remove_one_words_from_list(website_text, language) df.at[idx, 'text'] = processed_text print('****ARTICLE P & H{1}****', processed_text) except Exception as e: print(f"处理索引{idx}时出错: {e}") df.at[idx, 'text'] = '' # 修改调用逻辑,直接传递索引和原DataFrame for idx, status in df['status_code'].items(): if status != 200: get_the_text2(df, idx)
- 修复逻辑说明:
- 直接操作原DataFrame,避免传递单行Series导致的副本歧义
- 使用
.at[idx, 'text']精准定位赋值,完全符合Pandas安全索引规范,消除SettingWithCopyWarning - 移除函数内不必要的全局赋值
df['text']='',避免污染原数据集
内容的提问来源于stack exchange,提问作者Mostafa Bouzari
相关产品推荐
相关产品推荐

