基于最接近的匹配,使用Pandas合并数据框。

3

I have the following 2 dataframes (df_a,df_b):

df_a

    N0_YLDF
0   11.79
1   7.86
2   5.78
3   5.35
4   6.32
5   11.79
6   6.89
7   10.74


df_b
    N0_YLDF N0_DWOC
0   6.29    4
1   2.32    4
2   9.10    4
3   4.89    4
4   10.22   4
5   3.80    3
6   5.55    3
7   6.36    3

我想在df_a中添加一个名为N0_DWOC的列,该列的值来自于df_a ['N0_YLDF'] 最接近df_b ['N0_YLDF'] 行的值。

目前,我正在进行简单的合并操作,但这并不是我想要的结果。


1
请参见https://dev59.com/h2Mm5IYBdhLWcg3wO9Ly。 - Alexander
3个回答

4

您可以在 df_b['N0_YLDF'] 的(排序后的)值之间找到中点,这些中点就是截止值。然后使用这些截止值调用 pd.cut,将 df_a['N0_YLDF'] 中的值进行分类,其中截止值为分区边界:

import numpy as np
import pandas as pd

df_a = pd.DataFrame({ 'N0_YLDF': [11.79, 7.86, 5.78, 5.35, 6.32, 11.79, 6.89, 10.74]})
df_b = pd.DataFrame({ 'N0_YLDF':[6.29, 2.32, 9.10, 4.89, 10.22, 3.80, 5.55, 6.36] })

edges, labels = np.unique(df_b['N0_YLDF'], return_index=True)
edges = np.r_[-np.inf, edges + np.ediff1d(edges, to_end=np.inf)/2]
df_a['N0_DWOC'] = pd.cut(df_a['N0_YLDF'], bins=edges, labels=df_b.index[labels])
print(df_a)

产量
In [293]: df_a
Out[293]: 
   N0_YLDF N0_DWOC
0    11.79       4
1     7.86       2
2     5.78       6
3     5.35       6
4     6.32       0
5    11.79       4
6     6.89       7
7    10.74       4

要在两个数据框上使用 N0_DWOC 进行连接,可以使用以下代码:
print(df_a.join(df_b, on='N0_DWOC', rsuffix='_b'))

这将产生

   N0_YLDF N0_DWOC  N0_YLDF_b
0    11.79       4      10.22
1     7.86       2       9.10
2     5.78       6       5.55
3     5.35       6       5.55
4     6.32       0       6.29
5    11.79       4      10.22
6     6.89       7       6.36
7    10.74       4      10.22

我在上面的示例中没有包含它,但如果存在,join 将合并 df_b['N0_DWOC'] 作为名为 N0_DWOC_b 的新列。如果这不是您想要的,请更新您的问题以包括所需的输出。 - unutbu

3

另一种方法是对笛卡尔积中的所有项进行减法,并获取每个项最小绝对值的索引:

In [47]:ix = abs(np.atleast_2d(df_a['N0_YLDF']).T - df_b['N0_YLDF'].values).argmin(axis=1)
        ix
Out[47]: array([4, 2, 6, 6, 0, 4, 7, 4])

然后执行。
df_a['N0_DWOC'] = df_b.ix[ix, 'N0_DWOC'].values

In [73]: df_a
Out[73]:
N0_YLDF N0_DWOC
0   11.79   4
1   7.86    4
2   5.78    3
3   5.35    3
4   6.32    4
5   11.79   4
6   6.89    3
7   10.74   4

0

解决这个问题的另一种方法是执行笛卡尔积,然后计算共同列的值之间的绝对差。

然后按列N0_YLDF分组,获取差的最小值,并再次将其用于合并的df中,但这次使用合并作为过滤器。解释不充分,但您可能会看到代码在做什么。

mg = df_a.merge(df_b,how='cross')
mg['diff'] = mg.apply(lambda x:abs(x['N0_YLDF_x']-x['N0_YLDF_y']),axis=1 )
groups = mg.groupby('N0_YLDF_x')['diff'].min().reset_index()

mg.merge(groups.drop('N0_YLDF_x',axis=1), on='diff').drop(['N0_YLDF_y','diff'],axis=1).rename({'N0_YLDF_x':'N0_YLDF'})

输出 df


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接