Python 如何根据每个组在列中的顺序分配值?

Python 如何根据每个组在列中的顺序分配值?,python,pandas,dataframe,Python,Pandas,Dataframe,我有以下数据,值在End1,End2按顺序显示,我想有另一列,确定它在End1的显示顺序。End2处的值可能永远不会达到End1处,但如果它出现在任何地方,将对下一项的订单产生影响 ID End1 End2 1 A B 1 A B 1 B A 1 A B 1 C B 1 C D 1 D C 1 C D 1 D

我有以下数据,值在End1,End2按顺序显示,我想有另一列,确定它在End1的显示顺序。End2处的值可能永远不会达到End1处,但如果它出现在任何地方,将对下一项的订单产生影响

ID   End1   End2  
1    A      B      
1    A      B      
1    B      A     
1    A      B
1    C      B
1    C      D
1    D      C
1    C      D
1    D      C
2    A      B
2    A      B
2    A      C
2    A      C
2    C      A
2    C      A
2    D      C
2    C      D
2    D      C
我希望有以下输出:

ID   End1   End2  Order
1    A      B      1
1    A      B      1
1    B      A      2     
1    A      B      1
1    C      B      3 
1    C      D      3
1    D      C      4
1    C      D      3
1    D      C      4
2    A      B      1
2    A      B      1
2    A      C      1
2    A      C      1 
2    C      A      3
2    C      A      3
2    D      C      4
2    C      D      3
2    D      C      4
我尝试了不同的函数,但它们都在计算值的出现次数。感谢您的帮助

更新:这里还有两个其他要求:

  • 每个组的顺序都会重置。虽然A在ID=1中可能有顺序1,但在任何其他ID中可能有顺序2
  • 一些建议的解决方案没有考虑到End2处的项目(如ID=2中的B)可能永远不会到达End1处。但它会影响随后项目的顺序
  • 为了更清楚,同一数据集中的ID=3可能有以下数据:

    ID End1 End2
    2  D    C  
    .....  
    3  B    E 
    3  E    B
    3  E    B
    3  G    B
    3  C    B
    
    所需的输出将是

    ID End1 End2 Order
    2  D    C    4 
    .....  
    3  B    E    1
    3  E    B    2
    3  E    B    2 
    3  G    B    3
    3  C    B    4
    
    

    一种可能的方法是将End1+End2中的字符串值连接起来,并将结果用作字典的键。该算法类似于:

    counter = 1
    new_column = []
    my_dict = dict()
    for row in data:
      key_to_check = row[End1]+row[End2]
      if key_to_check in my_dict:
         new_column.append(my_dict[key_to_check])
      else:
         my_dict[key_to_check] = counter
         new_column.append(my_dict[key_to_check])
      counter += 1
    
    ## append new_column to the data
    
    将给出出场顺序

    序列
    中查找
    End1
    列中每个值的索引。按
    'ID'
    分组,因此顺序是
    'ID'
    唯一的。堆叠每个组/数据帧有助于展平
    ['End1','End2']

    df = df.set_index('ID')
    gb = df.groupby('ID')
    for k,g in gb:
        sequence = pd.unique(g.stack())
        order = (g.End1.to_numpy() == sequence[:,None]).argmax(0) + 1        
        df.loc[k,'Order'] = order
    df.Order = df.Order.astype(int)    
    


    将索引设置为
    ID
    ,并使用来重塑帧的形状,然后使用来创建一个识别不同值的数字数组,从而创建一个系列
    s
    ,然后使用
    s
    和agg,使用
    首先
    (因为我们必须首先优先考虑列
    End1
    的顺序,而不是
    End2
    ):

    <强>编辑< /强>:如果我们需要考虑<强>不同的< /强>每个组值:

    s = pd.Series(np.hstack([g.factorize()[0] + 1 for _, g in
                             df.set_index('ID').stack().groupby(level=0)]))
    df['Order'] = s.groupby(s.index // 2).first()
    
    结果:

        ID End1 End2  Order
    0    1    A    B      1
    1    1    A    B      1
    2    1    B    A      2
    3    1    A    B      1
    4    1    C    B      3
    5    1    C    D      3
    6    1    D    C      4
    7    1    C    D      3
    8    1    D    C      4
    9    2    A    B      1
    10   2    A    B      1
    11   2    A    C      1
    12   2    A    C      1
    13   2    C    A      3
    14   2    C    A      3
    15   2    D    C      4
    16   2    C    D      3
    17   2    D    C      4
    

    我只是尝试在每一行中输入列End1中的值出现的顺序号。因此,如果A在ID=1时首先出现,那么对于End1中的A和所有ID=1,顺序将是1。我希望我在这里讲得有道理。你想要的结果与更新的要求不符。@wwii-确实如此。可能所有的值都会以相同的顺序出现在其他ID上。或者其他ID可能有不同的值。因此我更新了我的其他要求。因此ID==2的顺序是
    ababacaca…
    ?为什么我需要连接End1+End2?顺序不取决于End1和END2的值。因此,做一把钥匙没有任何意义。谢谢。但它不会重置每个组的顺序,它只会查看End1的顺序并用于另一个组。@PulkitJain-您的示例看起来不像是重置为
    'ID'==2
    。。。您所需的输出显示订单的
    2ca
    ,值为
    3
    。@PulkitJain-我相信它是固定的。是的,Shubham sharma的回答成功了。
    s = pd.Series(df.set_index('ID').stack().factorize()[0] + 1)
    df['Order'] = s.groupby(s.index // 2).first()
    
    s = pd.Series(np.hstack([g.factorize()[0] + 1 for _, g in
                             df.set_index('ID').stack().groupby(level=0)]))
    df['Order'] = s.groupby(s.index // 2).first()
    
        ID End1 End2  Order
    0    1    A    B      1
    1    1    A    B      1
    2    1    B    A      2
    3    1    A    B      1
    4    1    C    B      3
    5    1    C    D      3
    6    1    D    C      4
    7    1    C    D      3
    8    1    D    C      4
    9    2    A    B      1
    10   2    A    B      1
    11   2    A    C      1
    12   2    A    C      1
    13   2    C    A      3
    14   2    C    A      3
    15   2    D    C      4
    16   2    C    D      3
    17   2    D    C      4