如何在数据框中检查每行的行号是否出现在列表列中?
给定一个数据框,我需要创建一个新的列叫做'flag',如果某一行的编号i
不在'id'这一列的任何列表中,那么这一行的'flag'值就为True,否则为False。
在下面的例子中,第1、3、5和6行的'flag'应该是True。我尝试用lambda表达式来实现,但没有成功。
import pandas as pd
pos = pd.DataFrame(columns=['id', 'pred'])
pos.loc[1,'id'] = [4, 4]
pos.loc[2,'id'] = [2]
pos.loc[3,'id'] = [2, 4]
pos.loc[4,'id'] = [2]
pos.loc[5,'id'] = [2, 4]
pos.loc[6,'id'] = [4]
for i in range(0, len(pos)):
pos['flag'] = pos.apply(lambda x: int(i in x['id']), axis=True)
print(pos)
id pred flag
1 [4, 4] NaN False
2 [2] NaN False
3 [2, 4] NaN False
4 [2, 6] NaN False
5 [2, 6] NaN False
6 [6] NaN False
4 个回答
2
这是一个和@Timeless的方法有点不同的做法,使用了集合的合并:
pos['flag'] = ~pos.index.isin(set().union(*pos['id']))
输出结果:
id pred flag
1 [4, 4] NaN True
2 [2] NaN False
3 [2, 4] NaN True
4 [2] NaN False
5 [2, 4] NaN True
6 [4] NaN True
3
我们可以把列 id
编译成一个集合:
ids = {e for v in pos['id'] for e in v}
{2, 4}
然后只需要简单地在索引上检查(是否不在) .isin()
:
pos['flag'] = ~pos.index.isin(ids)
id pred flag
1 [4, 4] NaN True
2 [2] NaN False
3 [2, 4] NaN True
4 [2] NaN False
5 [2, 4] NaN True
6 [4] NaN True
或者你也可以一行代码搞定:
pos['flag'] = ~pos.index.isin({e for v in pos['id'] for e in v})
这样做的好处是,相比于 展开 pos['id']
,你不会因为重复值而产生一个可能很大的中间值。这个集合的大小只会和独特元素的数量一样大。