如何在数据框中检查每行的行号是否出现在列表列中?

3 投票
4 回答
66 浏览
提问于 2025-04-14 16:33

给定一个数据框,我需要创建一个新的列叫做'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'],你不会因为重复值而产生一个可能很大的中间值。这个集合的大小只会和独特元素的数量一样大。

3

使用 (~)isin/explode:

pos["flag"] = ~pos.index.isin(pos["id"].explode()) # .astype(int) ?

输出结果 :

       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

[6 rows x 3 columns]

撰写回答