【问题标题】:How to maintain order when selecting rows in pandas dataframe?在熊猫数据框中选择行时如何保持顺序?
【发布时间】:2019-06-19 00:48:10
【问题描述】:

我想以列表中给定的特定顺序选择行。例如

这个数据框

a=[['car',1],['bike',3],['jewel',2],['tv',5],['phone',6]]

df=pd.DataFrame(a,columns=['items','quantity'])

>>> df
   items  quantity
0    car         1
1   bike         3
2  jewel         2
3     tv         5
4  phone         6

我想以['tv','car','phone'] 的顺序获取行,即第一行电视,然后是汽车,然后是电话。我试过这个方法,但它不能维持秩序

arr=['tv','car','phone']

df.loc[df['items'].isin(arr)]

   items  quantity
0    car         1
3     tv         5
4  phone         6

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    这是一个使用Index.get_indexer 的非侵入式解决方案,不涉及设置索引:

    df.iloc[pd.Index(df['items']).get_indexer(['tv','car','phone'])]
    
       items  quantity
    3     tv         5
    0    car         1
    4  phone         6
    

    请注意,如果这将成为一种常见的事情(按事情,我的意思是用列上的列表“索引”),您最好将该列转换为索引。如果你排序,奖励积分。

    df2 = df.set_index('items')
    df2.loc[['tv','car','phone']]  
    
           quantity
    items          
    tv            5
    car           1
    phone         6
    

    【讨论】:

      【解决方案2】:

      IIUCCategorical

      df=df.loc[df['items'].isin(arr)]
      df.iloc[pd.Categorical(df['items'],categories=arr,ordered=True).argsort()]
      Out[157]: 
         items  quantity
      3     tv         5
      0    car         1
      4  phone         6
      

      reindex:注意唯一不同的是这不会保存前一个索引,如果原始索引确实重要,您应该使用Categorical(由Andy L提到,如果您在项目中有重复,reindex失败

      df.set_index('items').reindex(arr).reset_index()
      Out[160]: 
         items  quantity
      0     tv         5
      1    car         1
      2  phone         6
      

      或者通过arr循环

      pd.concat([df[df['items']==x] for x in arr])
      Out[171]: 
         items  quantity
      3     tv         5
      0    car         1
      4  phone         6
      

      【讨论】:

      • reindex 如果他的真实数据有重复items 会失败?
      • @AndyL。会的,但是,他可以检查我提供的其他方法:-)
      • 酷!只是要求确保我不会误解reindex :)
      【解决方案3】:

      merge 救援:

      (pd.DataFrame({'items':['tv','car','phone']})
         .merge(df, on='items')
      )
      

      输出:

         items  quantity
      0     tv         5
      1    car         1
      2  phone         6
      

      【讨论】:

      • df 不是数组的顺序。
      • @YaakovBressler 是的,并且与从数组构造的数据框合并会解决这个问题。
      • 我不认为数组的顺序很重要,但如果是呢?有没有办法在合并中维护它?
      • 我不明白。这是在这里使用合并的目的。即merge保留GIVEN数组的顺序。
      • 我明白了。 我的错误,对不起。但是,原始索引丢失了。
      【解决方案4】:

      对于输入 df 中存在的所有要选择的项目,这里有一个 searchsorted 并且应该具有良好的性能 -

      In [43]: sidx = df['items'].argsort()
      
      In [44]: df.iloc[sidx[df['items'].searchsorted(['tv','car','phone'],sorter=sidx)]]
      Out[44]: 
         items  quantity
      3     tv         5
      0    car         1
      4  phone         6
      

      【讨论】:

        【解决方案5】:

        我会创建一个字典,从 arrmapitemsdropna, sort_values

        d = dict(zip(arr, range(len(arr))))
        
        Out[684]: {'car': 1, 'phone': 2, 'tv': 0}
        
        df.loc[df['items'].map(d).dropna().sort_values().index]
        
        Out[693]:
           items  quantity
        3     tv         5
        0    car         1
        4  phone         6
        

        【讨论】:

          【解决方案6】:

          这是另一个使用.loc 的变体。

          # Move items to the index, select, then reset.
          df.set_index("items").loc[arr].reset_index()
          

          或者其他不改变索引的。

          df.loc[df.reset_index().set_index("items").loc[arr]["index"]]
          

          【讨论】:

          • 请注意,.loc 不会保留多索引系列/数据帧中的顺序。单索引和多索引数据帧之间与.loc 的这种差异被认为是bugsolution 是 Pandas 1.1.0 里程碑的一部分。
          【解决方案7】:

          为什么不:

          >>> df.iloc[df.loc[df['items'].isin(arr), 'items'].apply(arr.index).sort_values().index]
             items  quantity
          3     tv         5
          0    car         1
          4  phone         6
          >>> 
          

          【讨论】:

            【解决方案8】:

            为什么不搜索索引、过滤和重新排序:

            df['new_order'] = df['items'].apply(lambda x: arr.index(x) if x in arr else -1)
            
            df_new = df[df['new_order']>=0].sort_values('new_order')
            
            
               items  quantity  new_order
            3     tv         5          0
            0    car         1          1
            4  phone         6          2
            
            

            【讨论】:

              猜你喜欢
              • 2020-12-09
              • 1970-01-01
              • 2014-08-30
              • 2019-01-27
              • 2018-10-09
              • 2017-08-04
              • 1970-01-01
              • 2020-12-23
              相关资源
              最近更新 更多