【问题标题】:How to efficiently find identical indices in multiple dataframes如何有效地在多个数据帧中找到相同的索引
【发布时间】:2017-06-27 17:54:43
【问题描述】:

我有一个收集一周内生成的报告并合并收集以消除相同报告的流程。

我编写了一个函数,该函数通过查找具有相同索引的报告来识别相同的报告,然后排除所有相同的报告,然后继续前进。虽然它适用于 5000-10,000 份报告,但处理 50,000 多份报告开始需要大量时间,随着时间的推移,这种情况将越来越普遍。

如果我可以先发制人地消除报告并避免此步骤,那就太好了,但是生成报告的过程不允许这样做。所以,我想找到一种方法让这个或类似的功能更有效。

代码如下:

def report_diff_index(self,dnc_data,folders):
    master_report_dict, master_val_dict = self.report_orderer(folders)
    sorts = self.report_sorter(dnc_data,master_report_dict)
    keys = [k for k in sorts.keys()]
    consolidated_sorts = keys
    print('Original Report Size: ', len(consolidated_sorts))
    for k in keys:
        if k in consolidated_sorts:
            for j in keys[keys.index(k)+1:]:
                if j in consolidated_sorts:
                    if len(list(set(sorts[k].index).symmetric_difference(sorts[j].index))) == 0:
                        consolidated_sorts.remove(j)
    print('Consolidated Report Size: ', len(consolidated_sorts))
    consolidated_report = {}
    consolidated_val = {}
    for s in consolidated_sorts:
        consolidated_report[s] = master_report_dict[s]
        consolidated_val[s] = master_val_dict[s]
    return consolidated_report, consolidated_val

【问题讨论】:

    标签: python list dictionary dataframe symmetric-difference


    【解决方案1】:

    我不知道我是否正确理解了您的问题,即使我理解了,我也不知道这是否更快,但是否可以创建一个使用唯一报告索引作为键的 dict (例如使用frozenset),然后将报告键作为值。这感觉像是建立唯一列表的更快方法,但我可能会离开:

    def report_diff_index(self,dnc_data,folders):
        master_report_dict, master_val_dict = self.report_orderer(folders)
        sorts = self.report_sorter(dnc_data,master_report_dict)
        print('Original Report Size: ', len(sorts))
        unique_reports = dict()
        for report_key, report in sorts.items:
            key = frozenset(report.index)
            # Alt 1. Replace with new (identical) repoirt
            unique_reports[key] = report_key
            # Alt 2. Keep first report
            if key not in unique_reports:
                unique_reports[key] = report_key
        consolidated_sorts = unique_reports.values()
        print('Consolidated Report Size: ', len(consolidated_sorts))
        consolidated_report = {}
        consolidated_val = {}
        for s in consolidated_sorts:
            consolidated_report[s] = master_report_dict[s]
            consolidated_val[s] = master_val_dict[s]
        return consolidated_report, consolidated_val
    

    如您所见,dict更新中还有两个选项,这取决于您是要保留第一个找到的报告还是无关紧要。

    插入 dict 应该接近 O(1),因此我想这会相当快。

    【讨论】:

    • 您不能直接使用它,但是任何不可变的,即可散列的数据都可以用作键。 sets 和 lists 是可变的,因此不能用作 dict keys,但是,frozensets 和 tuples 是不可变的,因此可以使用。因此,将您的索引转换为冻结集使它们可以用作键。
    • 非常感谢您的建议!我使用元组作为键来实现它,因为简短的测试表明它们的实例化比冻结集更快,并且它将 100,000 多个报告的处理时间减少到 4.5 秒!惊人。非常感谢!
    • @Dorian821 很高兴我能帮上忙。正如您所提到的,tuple:s 的生成速度比 set:s 更快。但是请记住,对于元组 (1, 2)(2, 1) 不同。因此,元素的顺序很重要。对于您当前的用例,这可能不是问题,但在某些情况下,它使 frozenset 成为更好的选择。
    【解决方案2】:

    如果我错了,请纠正我,但它看起来像:

    consolidated_sorts = keys
    print('Original Report Size: ', len(consolidated_sorts))
    for k in keys:
        if k in consolidated_sorts:
            for j in keys[keys.index(k)+1:]:
                if j in consolidated_sorts:
                    if len(list(set(sorts[k].index).symmetric_difference(sorts[j].index))) == 0:
                        consolidated_sorts.remove(j)
    

    只是寻找独特的报告。实际上,迭代是多余的,因为您首先将consolidated_sorts 设置为等于keys,然后迭代这些值并询问它们是否在consolidated_sorts 中,这是它们的来源。

    如果你只是想要唯一的键,你可以试试这样的:

    def report_diff_index(self,dnc_data,folders):
        master_report_dict, master_val_dict = self.report_orderer(folders)
        sorts = self.report_sorter(dnc_data,master_tree)
    
        # New code to create unique set of keys
        unique_keys = set(sorts.keys())
    
        consolidated_report = {}
        consolidated_val = {}
    
        for key in unique_keys:
            consolidated_report[key] = master_report_dict[key]
            consolidated_val[key] = master_val_dict[key]
    
        return consolidated_report, consolidated_val
    

    【讨论】:

    • 谢谢,但问题不在于查找唯一键,而在于查找字典中值的唯一索引。这就是为什么我要相互比较价值。
    • 您是否使用ordered dict,您认为您的字典有索引?或者您的dict 的结构如何?另外,我很惊讶这段代码目前对你有用。你理解这条线在做什么:if len(list(set(sorts[k].index).symmetric_difference(sorts[j].index))) == 0:?
    • @jack6e 不是说我是 Dorian821,而是该行将比较两个报告键列表并检查是否相等,而与列表中的键顺序无关。我想一个简单的set(sorts[k].index) == set(sorts[j].index) 会更有意义,但结果应该是一样的。
    • 我想他正在尝试这样做,但是尝试运行相同的代码会为我返回 TypeError,即 .index 方法作为内置方法是不可迭代的。我想知道他是否真的在尝试按照keys.index(k)keys.index(j) 的方式做一些事情。或者他可能正在尝试consolidated_sorts.index(k/j) 等。我仍然无法摆脱 OP 试图找到“字典中值的唯一索引”而不是“唯一键”的想法,好像dicts 有索引和不是钥匙。也许 OP 在列表和 dicts 之间的混淆是造成这种混淆的原因。
    • 感谢 cmets 的各位。这里的混乱似乎源于 dict 的值是数据帧而不是列表的事实,因此,如原始帖子中所述,索引是在 pandas 数据帧上调用的。当然,这可能不是总体上最好的方法,这正是我目前要做的。
    猜你喜欢
    • 1970-01-01
    • 2014-07-19
    • 2020-05-19
    • 2020-11-02
    • 2019-08-11
    • 2020-11-14
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多