使用for循环format赋值时出现ValueError:值长度与索引长度不匹配
问题回顾
我想用这段代码给DataFrame的go列批量生成字符串内容:
string="Verificamos {} vem crescendo em media {} porcento ao ano. A empresa {} por exemplo {}" df['go']=[string.format(*r) for r in dfcres[['CNAE_x','Crescimento_t11_Peers_CNAE','Top_Cres1','Top_Cres1%']].values.tolist()]
打印dfcres的目标列时,能看到正常的数据:
CNAE_x Crescimento_t11_Peers_CNAE Top_Cres1 Top_Cres1%
6 "bovinos" 0.10 "Maria Ltd" 0.22
8 "suínos" 0.08 "Carla Ltd" 0.10
9 "construção" 0.93 "Mark SA" 0.3...
但执行代码时直接报错:ValueError: Length of values does not match length of index,这可愁坏了,得赶紧解决。
问题根源
这个错误说白了就是你生成的字符串列表长度,和df的行数对不上。举个例子:如果dfcres有3行数据,生成的列表就有3个元素,但如果df有5行,那肯定塞不进去,直接报错。大概率是df和dfcres的行数不一致,比如dfcres是df过滤后的子集,或者两者的索引没有对应上。
靠谱的解决办法
1. 先排查行数是否匹配
先跑两行代码确认下两个DataFrame的行数:
print("df的行数:", len(df)) print("dfcres的行数:", len(dfcres))
如果行数不一样,那就是问题所在了。接下来就要看你想要的逻辑:是让df的每行都对应dfcres的行,还是只匹配有对应数据的行?
2. 用apply逐行生成(最稳妥的匹配方式)
如果df和dfcres有相同的索引,或者你想确保每行都能正确对应,先把需要的列合并到df里,再用apply逐行生成字符串:
# 把dfcres的目标列合并到df,按索引匹配 df = df.merge(dfcres[['CNAE_x','Crescimento_t11_Peers_CNAE','Top_Cres1','Top_Cres1%']], left_index=True, right_index=True, how='left') # 逐行填充go列 df['go'] = df.apply(lambda row: string.format( row['CNAE_x'], row['Crescimento_t11_Peers_CNAE'], row['Top_Cres1'], row['Top_Cres1%'] ), axis=1)
这种方式会自动处理索引匹配,就算dfcres里没有对应行,也会给df的对应位置留空(或者填充NaN),不会再报长度不匹配的错。
3. 先在dfcres生成列再合并
如果你的逻辑是基于dfcres的数据生成字符串,再同步到df,可以先在dfcres里生成go列,再合并到df:
# 先在dfcres里生成go列 dfcres['go'] = [string.format(*r) for r in dfcres[['CNAE_x','Crescimento_t11_Peers_CNAE','Top_Cres1','Top_Cres1%']].values.tolist()] # 把go列合并到df,按索引匹配 df = df.merge(dfcres[['go']], left_index=True, right_index=True, how='left')
这样生成的go列长度和dfcres一致,合并时按索引对应,也能避免长度问题。
4. 检查是否有缺失值
有时候dfcres的目标列可能有缺失值,导致生成列表时出问题?可以先检查下:
print(dfcres[['CNAE_x','Crescimento_t11_Peers_CNAE','Top_Cres1','Top_Cres1%']].isnull().sum())
如果有缺失值,要么填充默认值,要么删除对应行,再进行赋值操作。
内容的提问来源于stack exchange,提问作者aabujamra

