Pandas合并多列生成无重复无NaN的唯一值列表新列方法
解决方案
原代码残留NaN的原因很简单:set转换只会做值去重,不会自动过滤空值,而且numpy/pandas体系下的NaN不能靠普通的非空判断过滤,必须用pandas自带的空值检测方法。
下面给两种稳定可用的实现,根据数据规模选就行:
方法1:逐行处理(代码好懂,中小数据集首选)
import pandas as pd df['D'] = df[['A', 'B', 'C']].apply( lambda row: list(pd.unique([v for v in row if pd.notna(v)])), axis=1 )
逻辑说明:
- 内层列表推导式先逐值判断,用
pd.notna()过滤掉所有NaN、None类空值,兼容pandas所有空值类型,不会漏判 - 用
pd.unique()做去重,相比直接转set的优势是会保留值在原行里第一次出现的顺序,不会打乱元素排列 - 最终转成列表存入D列即可
方法2:原生聚合(性能更高,大数据量首选)
如果你的表行数在十万级以上,逐行apply的速度会偏慢,可以用pandas原生的堆叠聚合逻辑,性能是apply的3~5倍:
df['D'] = df[['A', 'B', 'C']].stack().groupby(level=0).unique().apply(list)
逻辑说明:
stack()操作会自动丢弃所有NaN值,把多列数据打平成带原行号索引的单列,天然完成空值过滤- 按原行号分组后直接调用
unique()做去重,最后转成列表即可,全程是pandas C层实现的逻辑,速度更快
运行以上任意一段代码,都能得到你预期的结果:
A B C D 0 "KFC" NaN "KFC" ["KFC"] 1 NaN "Mandai Zoo" "Singapore Zoo" ["Mandai Zoo", "Singapore Zoo"] 2 "Tampines Mall" NaN NaN ["Tampines Mall"]
小提示:如果你不需要保留列表内元素的原始顺序,可以把去重逻辑换成
set,运行速度会有小幅提升,但元素顺序会随机。
内容的提问来源于stack exchange,提问作者Ice
相关产品推荐
相关产品推荐

