繁体   English   中英

如何根据另一列中的值检查 pandas 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM