【问题标题】:find col2 values based on certain col1 value, if not presents keep nearest value using pandas根据某些 col1 值查找 col2 值,如果不存在,则使用 pandas 保持最近的值
【发布时间】:2019-05-16 13:10:32
【问题描述】:

我有一个这样的数据框:

df
col1      col2      
 1         10
 2         15
 4         12
 5         23
 6         11
 8         32
 9         12
 11        32
 2         23
 3         21
 4         12
 6         15
 9         12
 10        32

我想为 col1 的每 1、5 和 10 个值选择 col2 值。如果 col1 值不是 1、5 或 10,则保留 col1 值最接近 1,5 或 10 的 col2 值

例如,最终的 df 将如下所示:

df
col1      col2      
 1         10
 5         23
 11        32
 2         23
 6         15
 10        32

如何在不使用任何循环的情况下使用 pandas 来做到这一点

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:
    • df.col1.diff().lt(0).cumsum() 定义升序值组
    • set_index 与这些组 col1 但将col1drop=False 一起保留在数据框中
    • groupbypd.concat 使用 reindexmethod='nearest'

    我保留了旧的 col1 索引,以便您可以看到映射到什么。

    c = df.set_index([df.col1.diff().lt(0).cumsum().rename('grp'), 'col1'], drop=False)
    pd.concat([c.xs(k).reindex([1, 5, 10], method='nearest') for k, c in c.groupby(level=0)])
    
          col1  col2
    col1            
    1        1    10
    5        5    23
    10      11    32
    1        2    23
    5        6    15
    10      10    32
    

    如果你不喜欢索引中多余的col1,你可以重命名索引然后删除它:

    c = df.set_index([df.col1.diff().lt(0).cumsum().rename('grp'), 'col1'], drop=False)
    pd.concat([c.xs(k).reindex([1, 5, 10], method='nearest') for k, c in c.groupby(level=0)]) \
        .rename_axis(None).reset_index(drop=True)
    
       col1  col2
    0     1    10
    1     5    23
    2    11    32
    3     2    23
    4     6    15
    5    10    32
    

    【讨论】:

      【解决方案2】:

      试试这个:

      def extract_vals(x, vals=[1,5,10]):
          vals = np.array(vals)
          s = abs(x['col1'].values - vals[:,None])
      
          return x.iloc[s.argmin(axis=1)]
      
      s = df.col1.diff().lt(0).cumsum()
      df.groupby(s).apply(extract_vals).reset_index(drop=True)
      

      输出,由于第二组4,6的存在,与你的输出不同:

          col1    col2
      0   1       10
      1   5       23
      2   9       12
      3   2       23
      4   4       12
      5   10      32
      

      【讨论】:

        【解决方案3】:

        和pir的方法很相似

        s=df.col1.diff().lt(0).cumsum()
        idx=df.reset_index().groupby(s).apply(lambda x : x.set_index('col1').reindex([1,5,10],method='nearest'))['index']
        df.loc[idx]
        Out[19]: 
            col1  col2
        0      1    10
        3      5    23
        7     11    32
        8      2    23
        11     6    15
        13    10    32
        

        另一种获取索引的方法merge_asof

        df['key']=s
        import itertools
        l=list(itertools.product(df.key.unique().tolist(),[1,5,10]))
        mergedf=pd.DataFrame(l,columns=['key','col1']).astype(int)
        df.col1=df.col1.astype('int32')
        idx=pd.merge_asof(mergedf.sort_values('col1'),df.reset_index().sort_values('col1'),on='col1',by='key',direction ='nearest')['index']
        

        【讨论】:

          猜你喜欢
          • 2020-02-01
          • 1970-01-01
          • 2018-06-13
          • 2016-12-16
          • 1970-01-01
          • 1970-01-01
          • 2022-01-14
          • 1970-01-01
          • 2023-04-02
          相关资源
          最近更新 更多