Pandas无循环获取列表元素索引生成移位列报错排查与解决
无循环实现Pandas指定列元素在目标列表的索引移位生成新列
这个问题其实可以用非常简洁的字典映射来解决,完全不需要循环或者复杂的条件判断,而且效率还很高。先看最优解法:
import pandas as pd names = ["U9", "Z9", "H10"] dat = pd.DataFrame({'col1': ["U9", "U9", "U9", "Z9", "Z9", "H10", "H10", "H10", "H10", "H10"]}) # 直接创建"当前元素"到"下一个元素"的映射字典 name_to_next = {names[i]: names[i+1] for i in range(len(names)-1)} # 用map方法一键生成col2,不存在的键会自动填充NaN dat['col2'] = dat['col1'].map(name_to_next)
运行后得到的col2就是你想要的结果:["Z9", "Z9", "Z9", "H10", "H10", nan, nan, nan, nan, nan]
为什么原来的代码会报错?
你尝试的names[names.index(dat['col1'])+1]这里有个关键问题:names.index()方法只能接收单个元素,但你传入的是整个dat['col1'] Series,这就导致Python无法判断整个Series的真值,所以抛出了ValueError: The truth value of a Series is ambiguous的错误。
其他可选解法(进阶思路)
如果你需要保留索引的逻辑(比如后续可能有其他基于索引的操作),可以先把元素映射为索引,再通过索引获取下一个元素:
import pandas as pd import numpy as np names = ["U9", "Z9", "H10"] dat = pd.DataFrame({'col1': ["U9", "U9", "U9", "Z9", "Z9", "H10", "H10", "H10", "H10", "H10"]}) # 元素到索引的映射字典 name_to_idx = {name: idx for idx, name in enumerate(names)} dat['idx'] = dat['col1'].map(name_to_idx) # 利用np.where和Series索引生成col2 name_series = pd.Series(names) dat['col2'] = np.where( dat['idx'] < len(names)-1, name_series[dat['idx'] + 1].values, np.nan ) # 移除中间的idx列(可选) dat.drop('idx', axis=1, inplace=True)
这种方法的优势是可以保留索引信息做后续处理,不过对于当前问题来说,第一种字典直接映射的方法更简洁高效。
内容的提问来源于stack exchange,提问作者Nestoras Chalkidis
相关产品推荐
相关产品推荐

