根据某些 col1 值查找 col2 值,如果不存在,则使用 pandas 保持最近的值

Posted

技术标签:

【中文标题】根据某些 col1 值查找 col2 值,如果不存在,则使用 pandas 保持最近的值【英文标题】:find col2 values based on certain col1 value, if not presents keep nearest value using 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 来做到这一点

【问题讨论】:

【参考方案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']

【讨论】:

以上是关于根据某些 col1 值查找 col2 值,如果不存在,则使用 pandas 保持最近的值的主要内容,如果未能解决你的问题,请参考以下文章

Mysql - 根据重复的 Table_1 值更新某些 Table_2 值

遍历 pandas 行并根据其他列中的值设置列值

如何在sql中排除具有某些值的记录

根据其在另一列中的存在情况在 SQL 中打印值

根据另一个字段的值将字符串附加到 varchar2 字段

查找特定值的组合