加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – 按复杂条件合并/加入2个DataFrame

发布时间:2020-12-20 11:40:16 所属栏目:Python 来源:网络整理
导读:我有2个大型数据集(每个70K到110K大).我想关联/比较两者,并根据某些条件/标准找到set1中的哪些项目可以在set1中找到. 我当前的策略是按公共字段对两个列表进行排序,然后运行嵌套for循环,执行条件if测试,聚合预定义的dict与找到的项目和不匹配的项目. 例: im
我有2个大型数据集(每个70K到110K大).我想关联/比较两者,并根据某些条件/标准找到set1中的哪些项目可以在set1中找到.

我当前的策略是按公共字段对两个列表进行排序,然后运行嵌套for循环,执行条件if测试,聚合预定义的dict与找到的项目和不匹配的项目.

例:

import pandas as pd

list1 = [{'a': 56,'b': '38','c': '11','d': '10','e': 65},{'a': 31,'b': '12','c': '26','d': '99','e': 71},{'a': 70,'b': '49','c': '40','d': '227','e': 1},{'a': 3,'b': '85','c': '32','d': '46','e': 70},]
list2 = [{'a': 56,{'a': 145,'b': '108','c': '123','d': '84','e': 3},{'a': 113,'b': '144','c': '183','d': '7','e': 12},{'a': 144,'b': '60','c': '46','d': '106','e': 148},{'a': 57,'b': '87','c': '51','d': '95','e': 187},{'a': 41,{'a': 80,{'a': 107,'b': '95','c': '81','d': '15','e': 25},{'a': 138,'b': '97','c': '38','d': '28','e': 171}]

re_dict = dict([('found',[]),('alien',[])])

for L2 in list2:
    for L1 in list1:
        if (L1['a']-5 <= L2['a'] <= L2['a']+10) and L2['c'][-1:] in L1['c'][-1:]:
            if (65 <= L2['e'] <= 75):
                L2.update({'e': 'some value'})
            re_dict['found'].append(L2)
            list1.remove(L1)
            break # break out from the inner loop
    else: # if the inner loop traversed entire list,there were no matches
        re_dict['alien'].append(L2)

以上产生了预期结果:

re_dict
{'alien': [{'a': 145,'e': 171}],'found': [{'a': 56,'e': 'some value'},'e': 'some value'}]}

所以它完成了这项工作,但显然效率不高,似乎是大熊猫的理想工作.

我认为如果我可以合并/加入两个DataFrame,那将是理想的,但我无法弄清楚如何合并复杂的标准.我的数据集大小也不相同.

例:

df1 = pd.DataFrame(list1)
df2 = pd.DataFrame(list2)

pd.merge(df1,df2,on='d',how='outer')
   a_x  b_x  c_x    d  e_x  a_y  b_y  c_y  e_y
0   56   38   11   10   65   56   38   11   65
1   31   12   26   99   71   41   12   26   71
2   70   49   40  227    1   80   49   40    1
3    3   85   32   46   70    3   85   32   70
4  NaN  NaN  NaN   84  NaN  145  108  123    3
5  NaN  NaN  NaN    7  NaN  113  144  183   12
6  NaN  NaN  NaN  106  NaN  144   60   46  148
7  NaN  NaN  NaN   95  NaN   57   87   51  187
8  NaN  NaN  NaN   15  NaN  107   95   81   25
9  NaN  NaN  NaN   28  NaN  138   97   38  171

它仅在d d1和df2中d列完全相等时合并.
我更喜欢的是能够定义一个范围,即如果df2 [‘d’] – 5< = df1 ['d']< = df2 ['d'] 5它仍然可以,这意味着,两个数据帧中的这些行都是要合并的候选者,只有当测试失败时,df1列才会被NaN填充(如上例所示). 这样我可以在几个步骤中模仿我的嵌套for-for循环,希望这会更快? 任何建议/提示/示例将不胜感激. 谢谢

解决方法

pandas目前缺乏对“附近”查询的直接支持,尽管我有一个 pull request可以添加一些基本功能(对于你的用例来说还不够).

幸运的是,科学的Python生态系统为您提供了自己完成此操作所需的工具.

加入附近位置的有效方法是使用树数据结构,如scikit-learn documentation中所述.SciPy和scikit-learn都有合适的KDTree实现.

使用完全临时规则并不容易(或有效),但只要您有明确定义的距离度量,就可以有效地进行最近邻查找.我相信scikit-learn的KDTree甚至可以让你定义自己的距离度量,但我们会坚持正常的欧几里德距离继续你的例子:

from scipy.spatial import cKDTree as KDTree
import pandas as pd

# for each row in df2,we want to join the nearest row in df1
# based on the column "d"
join_cols = ['d']
tree = KDTree(df1[join_cols])
distance,indices = tree.query(df2[join_cols])
df1_near_2 = df1.take(indices).reset_index(drop=True)

left = df1_near_2.rename(columns=lambda l: 'x_' + l)
right = df2.rename(columns=lambda l: 'y_' + l)
merged = pd.concat([left,right],axis=1)

这导致:

x_a x_b x_c  x_d  x_e  y_a  y_b  y_c  y_d  y_e
0   56  38  11   10   65   56   38   11   10   65
1   31  12  26   99   71  145  108  123   84    3
2   56  38  11   10   65  113  144  183    7   12
3   31  12  26   99   71  144   60   46  106  148
4   31  12  26   99   71   57   87   51   95  187
5   31  12  26   99   71   41   12   26   99   71
6   70  49  40  227    1   80   49   40  227    1
7    3  85  32   46   70    3   85   32   46   70
8   56  38  11   10   65  107   95   81   15   25
9   56  38  11   10   65  138   97   38   28  171

如果你想基于多列的接近度进行合并,就像设置join_cols = [‘d’,’e’,’f’]一样简单.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读