如何在Pandas方法链中计算列表列行间共同元素数量并解决类型错误
Pandas方法链中计算列表列前后行共同元素数量
问题描述
需要在Pandas方法链中计算列表列某一行与前一行的共同元素数量,但编写的代码抛出TypeError: unhashable type: 'list'错误,相关代码如下:
import pandas as pd df = pd.DataFrame({ 'x':[1,2,3,4], 'list_column': [ ['apple', 'banana', 'cherry'], ['banana', 'cherry'], ['cherry', 'date', 'fig'], ['orange'] ] }) res = len(set(df.loc[1,'list_column']) & set(df.loc[0,'list_column'])) res df=(df .assign( list_length=lambda x: x['list_column'].str.len(), nr_common=lambda x: (set(x['list_column']) & set(x['list_column'].shift(1))).len() ) ) df
错误原因
报错核心是:x['list_column']是Series对象,直接对它调用set()会尝试把Series中的每个列表元素存入集合,但列表是不可哈希的类型,无法作为集合元素,因此触发TypeError。而单独取某一行的列表(如df.loc[1,'list_column'])转集合可行,是因为此时操作的是单个列表而非整个Series。
解决方案
通过apply结合shift()逐行处理当前行与前一行的列表,计算交集长度。修改后的方法链代码如下:
方案一:借助中间列实现
import pandas as pd df = pd.DataFrame({ 'x':[1,2,3,4], 'list_column': [ ['apple', 'banana', 'cherry'], ['banana', 'cherry'], ['cherry', 'date', 'fig'], ['orange'] ] }) df = (df .assign( list_length=lambda x: x['list_column'].str.len(), prev_list=lambda x: x['list_column'].shift(1) ) .assign( nr_common=lambda x: x.apply( lambda row: len(set(row['list_column']) & set(row['prev_list'])) if pd.notna(row['prev_list']) else pd.NA, axis=1 ) ) .drop(columns='prev_list') ) print(df)
方案二:直接引用shift后的Series
如果不想创建中间列,可以直接在apply中调用移位后的列:
df = (df .assign( list_length=lambda x: x['list_column'].str.len(), nr_common=lambda x: x.apply( lambda row: len(set(row['list_column']) & set(x['list_column'].shift()[row.name])) if row.name > 0 else pd.NA, axis=1 ) ) )
执行后输出结果:
x list_column list_length nr_common 0 1 [apple, banana, cherry] 3 <NA> 1 2 [banana, cherry] 2 2 2 3 [cherry, date, fig] 3 1 3 4 [orange] 1 0
内容的提问来源于stack exchange,提问作者Zeus
相关产品推荐
相关产品推荐

