【问题标题】:Identify records that are present in particular set of years and not in the another set of years识别出现在特定年份而不是另一组年份的记录
【发布时间】:2022-07-20 01:48:37
【问题描述】:

我正在尝试根据 ID 和年份标记行,如果 ID 出现在 [2017,2018,2019] 年份并且 未出现 在 [2020,2021,2022] 中,则需要将其标记为 1 else 0。

df1 = pd.DataFrame({'ID': ['AX1', 'Ax1', 'AX1','AX1','AX1','AX1','AX2','AX2','AX2','AX3','AX3','AX4','AX4','AX4'],'year':[2017,2018,2019,2020,2021,2022,2019,2020,2022,2019,2020,2017,2018,2019]})

     ID  year
0   AX1  2017
1   Ax1  2018
2   AX1  2019
3   AX1  2020
4   AX1  2021
5   AX1  2022
6   AX2  2019
7   AX2  2020
8   AX2  2022
9   AX3  2019
10  AX3  2020
11  AX4  2017
12  AX4  2018
13  AX4  2019

预期输出:

     ID  year  label
0   AX1  2017      0
1   Ax1  2018      0
2   AX1  2019      0
3   AX1  2020      0
4   AX1  2021      0
5   AX1  2022      0
6   AX2  2019      0
7   AX2  2020      0
8   AX2  2022      0
9   AX3  2019      0
10  AX3  2020      0
11  AX4  2017      1
12  AX4  2018      1
13  AX4  2019      1

在上面的示例中 ID:AX4 被标记为 1,因为它是唯一出现在第一组年份 [2017,2018,2019] 并且没有出现在第二组年份 [2020] 中的 ID ,2021,2022]。

我如何做到这一点?

【问题讨论】:

    标签: python python-3.x pandas dataframe


    【解决方案1】:

    按 ID 分组,使用集合操作检查是否需要的年份和不需要的年份,并将结果映射回df1

    df1 = pd.DataFrame({'ID': ['AX1', 'AX1', 'AX1','AX1','AX1','AX1','AX2','AX2','AX2','AX3','AX3','AX4','AX4','AX4'],'year':[2017,2018,2019,2020,2021,2022,2019,2020,2022,2019,2020,2017,2018,2019]})
    
    # find group level labels by checking if all of 2017-19 and none of 2020-22 exist for each ID
    gr_lbl = df1.groupby('ID')['year'].apply(lambda g: {2017,2018,2019}.issubset(g) and not bool({2020,2021,2022}.intersection(g)))*1
    # map group level labels to ID
    df1['labels'] = df1['ID'].map(gr_lbl)
    

    另一个(更易读的代码)是交叉制表df1 并检查跨列的年份。 pd.crosstab() 对列进行排序(在本例中为年份),所以简单的 eq() 可以工作。

    # cross tabulate and check for years across columns
    labels = pd.crosstab(df1['ID'], df1['year']).eq([1,1,1,0,0,0], axis=1).all(1)*1
    # map group level labels to ID
    df1['labels'] = df1['ID'].map(labels)
    df1
    

    【讨论】:

      【解决方案2】:
      import pandas as pd
      
      df1 = pd.DataFrame({'ID': ['AX1', 'Ax1', 'AX1','AX1','AX1','AX1','AX2','AX2','AX2','AX3','AX3','AX4','AX4','AX4'],'year':[2017,2018,2019,2020,2021,2022,2019,2020,2022,2019,2020,2017,2018,2019]})
      
      include = set()
      exclude = set()
      
      for ID, year in zip(df1['ID'], df1['year']):
          if year in [2017,2018,2019]:
              include.add(ID.upper())
          if year in [2020,2021,2022]:
              exclude.add(ID.upper())
              
      df1['label'] = [int(x.upper() in include - exclude) for x in df1['ID']]
      
      print(df1)
      

      【讨论】:

        【解决方案3】:

        通过聚合sets 创建Series,然后通过set.issubset 进行比较,最后将输出映射到新列:

        y1 = set([2017,2018,2019])
        y2 = set([2020,2021,2022])
        
        s = df1.groupby('ID')['year'].agg(set)
        df1['label'] = df1['ID'].map((s.map(y1.issubset) & ~s.map(y2.issubset)).astype(int))
        print (df1)
             ID  year  label
        0   AX1  2017      0
        1   Ax1  2018      0
        2   AX1  2019      0
        3   AX1  2020      0
        4   AX1  2021      0
        5   AX1  2022      0
        6   AX2  2019      0
        7   AX2  2020      0
        8   AX2  2022      0
        9   AX3  2019      0
        10  AX3  2020      0
        11  AX4  2017      1
        12  AX4  2018      1
        13  AX4  2019      1
        

        详情

        print (df1.groupby('ID')['year'].agg(set))
        ID
        AX1    {2017, 2019, 2020, 2021, 2022}
        AX2                {2019, 2020, 2022}
        AX3                      {2019, 2020}
        AX4                {2017, 2018, 2019}
        Ax1                            {2018}
        Name: year, dtype: object()
        
        print ((s.map(y1.issubset) & ~s.map(y2.issubset)).astype(int))
        ID
        AX1    0
        AX2    0
        AX3    0
        AX4    1
        Ax1    0
        Name: year, dtype: int32
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-25
          • 2012-02-14
          相关资源
          最近更新 更多