【问题标题】:Ordering across columns in a dataframe based on a custom list根据自定义列表对数据框中的列进行排序
【发布时间】:2019-03-21 14:28:07
【问题描述】:

我可以看到垂直排序记录的解决方案,但是我想在我的数据框中水平排列我的数据子集。

这是我想要排序的数据的数据框:

account_num Word_0    Word_1    Word_2    Word_3    Word_4
123         Silver    Platinum  Osmium    
456         Platinum  
789         Silver    Rhodium   Platinum  Osmium    

这是我想要的输出:

account_num  Word_0     Word_1    Word_2   Word_3   Word_4
123          Platinum   Osmium    Silver   
456          Platinum   
789          Rhodium    Platinum  Osmium   Silver   

基于此数据框中的顺序:

Priority    Metal
1           Rhodium
2           Platinum
3           Gold
4           Ruthenium
5           Iridium
6           Osmium
7           Palladium
8           Rhenium
9           Silver
10          Indium

我已经设法使用这段代码整理了我的数据:

newdf.apply(lambda r: sorted(r,reverse = True), axis = 1)

Word_0 到 4 列被放置在另一个数据框 (newdf) 中,然后以相反的顺序排序,因此空白值最后出现,然后它们被连接回包含 account_num 列的原始数据框,但是我不知道如何合并排序顺序中的自定义列表。

任何帮助将不胜感激

谢谢

【问题讨论】:

    标签: python-3.x pandas sorting dataframe


    【解决方案1】:

    使用pd.Categorical

    c = pd.Categorical(df2.Metal, df2.Metal, ordered=True)
    
    df.set_index('account_num').transform(lambda k: pd.Categorical(k, 
                                                               categories=c.categories)\
                                      .sort_values(), axis=1)
    

    输出

                Word_0       Word_1     Word_2  Word_3  Word_4
    account_num                 
    123         Platinum     Osmium     Silver  NaN     NaN
    456         Platinum     NaN        NaN     NaN     NaN
    789         Rhodium      Platinum   Osmium  Silver  NaN
    

    当然可以.fillna('')到底。​​p>

    【讨论】:

    • 我真的要学习 pd.Categorical() 在很多情况下似乎非常有用。 :)
    【解决方案2】:

    你也可以试试:

    df=df.fillna(value=pd.np.nan)
    d=dict(zip(ref.Metal,ref.Priority))
    df[['account_num']].join(pd.DataFrame(np.sort(df.iloc[:,1:].replace(d).values,axis=1),
                            columns=df.iloc[:,1:].columns).replace({v:k for k,v in d.items()}))
    
       account_num    Word_0    Word_1  Word_2  Word_3 Word_4
    0          123  Platinum    Osmium  Silver     NaN    NaN
    1          456  Platinum       NaN     NaN     NaN    NaN
    2          789   Rhodium  Platinum  Osmium  Silver    NaN
    

    【讨论】:

      【解决方案3】:

      我觉得我们可以melt it ,merge 订单 df ,然后 sort_values 基于 Prioritypivot it back

      s=df.melt('account_num').\
           merge(orderdf,left_on='value',right_on='Metal',how='left').\
             sort_values('Priority')
      yourdf=s.assign(newkey=s.groupby('account_num').cumcount()).\
                 pivot('account_num','newkey','value').add_prefix('Word_')
      yourdf
      Out[1100]: 
      newkey         Word_0    Word_1  Word_2  Word_3 Word_4
      account_num                                           
      123          Platinum    Osmium  Silver    None    NaN
      456          Platinum      None    None    None    NaN
      789           Rhodium  Platinum  Osmium  Silver    NaN
      

      或者我们使用更清晰的逻辑argsort

      d = dict(zip(df2['Metal'], df2['Priority']))
      for x in range(len(df)):
      
          df.iloc[x,:]=df.values[x,np.argsort([d.get(x) if x ==x else 1000 for x in df.values[x,:]] )]
      
      df
      Out[38]: 
                       Word_0    Word_1  Word_2  Word_3  Word_4
        account_num                                            
      0 123          Platinum    Osmium  Silver     NaN     NaN
      1 456          Platinum       NaN     NaN     NaN     NaN
      2 789           Rhodium  Platinum  Osmium  Silver     NaN
      

      【讨论】:

        【解决方案4】:

        用途:

        #create helper dictionary
        d = dict(zip(df2['Metal'], df2['Priority']))
        #add empty string for maximum priority
        d[''] = df2['Priority'].max() + 1
        
        #use sorted by key and dictioanry
        L = [sorted(x, key=d.get) for x in df.fillna('').values]
        #create new DataFrame by constructor
        df1 = pd.DataFrame(L, index=df.index).add_prefix('Word_')
        print (df1)
                       Word_0    Word_1  Word_2  Word_3 Word_4
        account_num                                           
        123          Platinum    Osmium  Silver               
        456          Platinum                                 
        789           Rhodium  Platinum  Osmium  Silver     
        

        如果需要缺失值:

        df1 = pd.DataFrame(L, index=df.index).add_prefix('Word_').replace('', np.nan)
        print (df1)
                       Word_0    Word_1  Word_2  Word_3  Word_4
        account_num                                            
        123          Platinum    Osmium  Silver     NaN     NaN
        456          Platinum       NaN     NaN     NaN     NaN
        789           Rhodium  Platinum  Osmium  Silver     NaN  
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-12-18
          • 2014-12-29
          • 2022-07-05
          • 1970-01-01
          • 2021-09-10
          • 1970-01-01
          • 2019-03-07
          • 1970-01-01
          相关资源
          最近更新 更多