pandas如何用列表对应替换子DataFrame指定列的所有值
问题根源
报错来自索引匹配逻辑错误:
- 原代码爬取每个url生成子DataFrame时,给Title列固定填充了
'Change'占位,没有同步关联l_names的对应位置值 - 直接传入整个
l_names作为插入值时,pandas要求传入序列长度必须和当前子DataFrame的行数完全相等,长度为83的剧名列表匹配行数为8左右的子表,必然触发长度不匹配的ValueError - 在url遍历循环内嵌套遍历
l_names,会重复给同一个子表赋值Title列,导致列重名、值循环错乱的问题
实现方案
二选一即可,推荐优先用方案1,减少冗余处理步骤。
方案1:修改爬取循环逻辑(推荐)
爬取时用enumerate同步获取当前url的遍历索引,插入Title列时直接取l_names对应索引的剧名,不需要先填占位符再替换,修改后的完整爬取代码如下:
l_names = [] for l in links: l_names.append(l.get_text()) df = [] # 遍历url时同步拿到索引值 for idx, u in enumerate(urls): req = s.get(u) req_soup = BeautifulSoup(req.content, 'lxml') req_tables = req_soup.find_all('table', {'class':'infobox vevent'}) req_df = pd.read_html(str(req_tables), flavor='bs4', header=0) dfr = pd.concat(req_df) dfr = dfr.drop(index=0) dfr.columns = range(dfr.columns.size) dfr[1] = dfr[1].str.replace(r"([A-Z])", r" \1").str.strip().str.replace(' ', ' ') dfr = dfr[~dfr[0].isin(remove_list)] dfr = dfr.dropna() dfr = dfr.reset_index(drop=True) # 直接插入对应位置的剧名,无需填充Change占位 dfr.insert(loc=0, column='Title', value=l_names[idx]) df.append(dfr)
注意:该方案要求
urls的遍历顺序和采集l_names时links的遍历顺序完全一一对应,否则会出现剧名和剧集信息错位的问题。
方案2:批量替换已生成的df列表
如果已经跑完原有爬取代码,不想重跑流程,可以直接用zip配对每个子DataFrame和对应剧名,批量替换Title列的值:
# 逐个子表匹配对应剧名,自动填充整列 for sub_df, drama_name in zip(df, l_names): sub_df['Title'] = drama_name
该写法传入的是单个字符串值,pandas会自动将值填充到子表Title列的所有行,不会触发长度不匹配错误,也不会产生重复列。
效果验证
处理完成后,子表的Title列会按索引匹配对应剧名,示例中前4个子表的Title值分别为:
- 第一个子表:
Babel - 第二个子表:
Baby Faced Beauty - 第三个子表:
Babysitter - 第四个子表:
Bachelor's Vegetable Store
全部83个子表都会完成正确匹配,无列重复、值错乱问题。
内容的提问来源于stack exchange,提问作者jaymerson
相关产品推荐
相关产品推荐

