【问题标题】:Substituting python list for dataframe用python列表替换数据框
【发布时间】:2021-08-24 10:24:46
【问题描述】:

我有一个代码可以在我的文本文件中的数据之间创建邻接关系。文件结构非常简单。它只有 2 列描述 2 个节点之间的连接。例如:

ANALYTICAL_BALANCE BFG_DEPOSIT
CUSTOMER_DETAIL BALANCE
BFG_2056 FFD_15
BALANCE BFG_16
BFG_16 STAT_HIST
ANALYTICAL_BALANCE BFG_2056
CUSTOM_DATA AND_11
AND_11 DICT_DEAL
DICT_DEAL BFG_2056

我现在将数据加载到列表中。

data = [line.split() for line in open('data.txt', sep=' ')

我得到这样的列表

data = [
    ["ANALYTICAL_BALANCE","BFG_DEPOSIT"],
    ["CUSTOMER_DETAIL","BALANCE"],
    ["BFG_2056", "FFD_15"],
    ["BALANCE","BFG_16"],
    ["BFG_16","STAT_HIST"],
    ["ANALYTICAL_BALANCE","BFG_2056"],
    ["CUSTOM_DATA","AND_11"],
    ["AND_11","DICT_DEAL"],
    ["DICT_DEAL","BFG_2056"]
]

然后我创建邻接列表

def create_adj(edges):
    adj = {}   # or use defaultdict(list) to avoid `if` in the loop below
    for a, b in edges:
        if not a in adj:
            adj[a] = []
        if not b in adj:
            adj[b] = []
        adj[a].append(b)
    return adj

并返回所有路径

def all_paths(adj):
    def recur(path):
        node = path[-1]
        neighbors = [neighbor for neighbor in adj[node] if not neighbor in path]
        if not neighbors:
            yield path
        for neighbor in neighbors:
            yield from recur(path + [neighbor])

    for node in adj:
        yield from recur([node])

所以例如我之前给出的,输出数据将是这样的。我不打印长度等于 1 的列表。

adj = create_adj(data)

paths = all_paths(adj)

for i in paths:
    if len(i) > 1:
        print(i)
output:
['ANALYTICAL_BALANCE', 'BFG_DEPOSIT']
['ANALYTICAL_BALANCE', 'BFG_2056', 'FFD_15']
['CUSTOMER_DETAIL', 'BALANCE', 'BFG_16', 'STAT_HIST']
['BALANCE', 'BFG_16', 'STAT_HIST']
['BFG_2056', 'FFD_15']
['BFG_16', 'STAT_HIST']
['CUSTOM_DATA', 'AND_11', 'DICT_DEAL', 'BFG_2056', 'FFD_15']
['AND_11', 'DICT_DEAL', 'BFG_2056', 'FFD_15']
['DICT_DEAL', 'BFG_2056', 'FFD_15']

虽然数据集很小,但一切都很好,但我在 txt 文件中有近 13k 行此连接。编译时间太长了。这就是为什么我想将列表上的所有操作更改为 pandas 数据帧。我不知道怎么做,因为我没有这方面的经验。你会怎么做?也许你有更好的想法我可以如何实现我的想法。我也在考虑使用 Networkx,但我不知道如何使用它来实现我的代码。任何帮助将不胜感激!

【问题讨论】:

  • 您会遇到的一个问题是路径的总数会随着图的大小呈指数增长。
  • @jhylands 我知道这一点,但我仍然希望将列表更改为数据框可以加快进程。尤其是对于更大的数据。
  • 我对此的理解是最慢的部分将是打印。使用不同的框架不会加快速度。如果您正在寻找路径列表中的路径,那么您可以在路径生成级别应用启发式方法。由于您似乎想要 all 打印路径,因此没有更快的方法。
  • 我能想到的另一件事是将所有信息保存在内存中,在缓冲区中生成打印输出,然后打印该缓冲区。所以不是print(i)acc += str(i)然后在循环之外print(acc)
  • 对于如此大的输入,您是否希望输出存储在文件中而不是打印到终端?

标签: python pandas algorithm networkx


【解决方案1】:

使用 pandas 不会加快速度,或者至少不会显着加快速度,因为 pandas DataFrame 旨在处理表格数据,并没有针对数据的网络结构进行优化。

使用 networkx 肯定会简化您的代码,但恐怕它也不会显着加快您的速度,因为这个库是由纯 python 构建的,与您的代码相同.

通过使用其他快速库,例如 igraph 或 turicreate 的 SGraph 对象,您将获得更好的性能。对于这两个库,需要习惯使用它们,但两者肯定会为您加快速度。

另一种加快速度的方法当然是为您的问题找到一个合适的更快的算法。

现在,更实际一点,您实际上在做的是生成图的所有可能的生成树。也许here 你可以找到一些很好的参考,找到合适的算法,用更少的步骤实现你想要的。

还发现this 其中包括一个建议查找所有最小生成树的代码的答案。您可以看到它如何创建 networkx 的 Graph 对象并使用该函数。然后你可以为所有边分配相同的权重,它只会在图中找到你所有的生成树。

【讨论】:

  • 这就是我想要的。我找不到合适的词来解释我想要得到的东西,但是“生成所有可能的生成树”非常合适。唯一的缺点是我需要创建很多它们并过滤它们,但我会为此发表其他帖子,也许有人会给出答案。谢谢!
  • 毫无疑问,对于 13k 边,它会产生很多。您没有提到任何关于过滤的内容,在这种情况下,您可以使用 yield 并从建议的函数创建一个生成器,并在生成它们时过滤它们,而不是聚合所有结果的巨大列表然后过滤。
  • 如果你想检查它,我添加了整个问题和整个想法。 stackoverflow.com/questions/68921115/…
猜你喜欢
  • 1970-01-01
  • 2019-12-02
  • 2017-08-03
  • 2018-02-11
  • 2020-01-12
  • 1970-01-01
  • 2021-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多