![](/img/trans.png)
[英]Pandas: Check if value in one df exists in any column of another DF
[英]How do I check if pandas df column value exists based on value in another column?
我有一个如下所示的熊猫数据框
年 | ID | 价值 |
---|---|---|
2016年 | 1 | 100 |
2017年 | 1 | 102 |
2017年 | 1 | 105 |
2018年 | 1 | 98 |
2016年 | 2 | 121 |
2016年 | 2 | 101 |
2016年 | 2 | 133 |
2018年 | 3 | 102 |
我想检查该 ID 是否仅存在于 2018 年。 我想要的输出如下:
年 | ID | 价值 | ID_only_in_2018 |
---|---|---|---|
2016年 | 1 | 100 | 0 |
2017年 | 1 | 102 | 0 |
2017年 | 1 | 105 | 0 |
2018年 | 1 | 98 | 0 |
2016年 | 2 | 121 | 0 |
2016年 | 2 | 101 | 0 |
2016年 | 2 | 133 | 0 |
2018年 | 3 | 102 | 1 |
请问,我怎样才能在python中实现这一点?
比较2018
年份,然后测试所有值是否仅为2018
:
mask = df['Year'].eq(2018).groupby(df['ID']).transform('all')
另一个想法是测试 Year 是否不是2018
,过滤器ID
不匹配至少一个非2018
行和最后一个反转掩码~
只获取2018
组:
mask = ~df['ID'].isin(df.loc[df['Year'].ne(2018), 'ID'])
最后将掩码转换为整数:
df['ID_only_in_2018'] = mask.astype(int)
或者:
df['ID_only_in_2018'] = np.where(mask, 1, 0)
或者:
df['ID_only_in_2018'] = mask.view('i1')
print (df)
Year ID Value ID_only_in_2018
0 2016 1 100 0
1 2017 1 102 0
2 2017 1 105 0
3 2018 1 98 0
4 2016 2 121 0
5 2016 2 101 0
6 2016 2 133 0
7 2018 3 102 1
对于每组ID
,我们可以使用isin
检查它们唯一的Year
是否等于[2018]
。 然后我们可以map
框架中的所有ID
:
only_2018 = df.groupby("ID").Year.unique().isin([[2018]])
df["ID_only_in_2018"] = df.ID.map(only_2018).astype(int)
其中 2018 年左右的双括号是因为unique
返回了一个列表,所以我们放了另一个,而astype
是将 True/False 转换为 1/0。
要得到
>>> df
Year ID Value ID_only_in_2018
0 2016 1 100 0
1 2017 1 102 0
2 2017 1 105 0
3 2018 1 98 0
4 2016 2 121 0
5 2016 2 101 0
6 2016 2 133 0
7 2018 3 102 1
only_2018
是:
ID
1 False
2 False
3 True
如果年份是唯一的,并且这个唯一的年份是 2018,你必须在你的组ID
进行测试:
df['ID_only_in_2018'] = df.groupby('ID')['Year'] \
.apply(lambda y: (y.nunique() == 1) &
(y == 2018)).astype(int)
>>> df
Year ID Value ID_only_in_2018
0 2016 1 100 0
1 2017 1 102 0
2 2017 1 105 0
3 2018 1 98 0
4 2016 2 121 0
5 2016 2 101 0
6 2016 2 133 0
7 2018 3 102 1
第一次重新创建示例:
import pandas as pd
data = [{"Year" : 2016, "ID" : 1, "Value" : 100},
{"Year" : 2017, "ID" : 1, "Value" : 102},
{"Year" : 2017, "ID" : 1, "Value" : 105},
{"Year" : 2018, "ID" : 1, "Value" : 98},
{"Year" : 2016, "ID" : 2, "Value" : 121},
{"Year" : 2016, "ID" : 2, "Value" : 101},
{"Year" : 2016, "ID" : 2, "Value" : 133},
{"Year" : 2018, "ID" : 3, "Value" : 102}]
df = pd.DataFrame(data)
并仔细查看汇总数据,看看是什么。
df.groupby("ID")['Year'].apply(list)
返回以下内容:
ID 1 [2016, 2017, 2017, 2018]
2 [2016, 2016, 2016]
3 [2018] Name: Year, dtype: object
因此,ID 1 出现在所有 4 年中,ID 2 出现了 3 次,但仅在 2016 年出现过,而 ID 3 仅出现一次,即 2018 年。
将聚合函数从list
更改为set
返回略有不同的视图:
df.groupby("ID")['Year'].apply(set)
ID
1 {2016, 2017, 2018}
2 {2016}
3 {2018}
Name: Year, dtype: object
这显示了 ID 1 如何跨 3 年分布,而 ID 2 和 3 分别仅分布在一年中。
如果您想测试给定的 ID 是否仅与一年相关联,您可以保存并参考这些字典之一,测试所选年份的返回值。
unique_lookup_set = dict(df.groupby("ID")['Year'].apply(set))
def contains_and_only_contains(value, collection):
if value in collection and len(set(collection))==1:
return 1
else:
return 0
现在尝试用答案生成一个系列,以测试它:
df.apply(lambda x : contains_and_only_contains(2018, unique_lookup_set.get(x['ID'])), axis=1)
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 1
dtype: int
很好,最后,将该系列包含到原始数据帧中以获得最终输出。
df['ID_only_in_2018']=df.apply(lambda x : contains_and_only_contains(2018, unique_lookup_set.get(x['ID'])), axis=1)
df
年 | ID | 价值 | ID_only_in_2018 | |
---|---|---|---|---|
0 | 2016年 | 1 | 100 | 0 |
1 | 2017年 | 1 | 102 | 0 |
2 | 2017年 | 1 | 105 | 0 |
3 | 2018年 | 1 | 98 | 0 |
4 | 2016年 | 2 | 121 | 0 |
5 | 2016年 | 2 | 101 | 0 |
6 | 2016年 | 2 | 133 | 0 |
7 | 2018年 | 3 | 102 | 1 |
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.