【问题标题】:Recursive self join and transposition递归自连接和转置
【发布时间】:2019-01-09 23:17:56
【问题描述】:

我有一个跨多个测量周期跟踪父/子关系的数据集。这看起来像

[["Col1","Col2"],
 ["A","B"],
 ["B","C"],
 ["C","D"]]

我希望它显示为

[["Col1","Col2","Col3","Col4"],
 ["A","B","C","D"]]

我在 SQL 中看到过其他示例,但这些示例似乎都没有回答我的问题。我正在寻找数据的完整列扩展。

我研究了自连接和转置,但这些都没有让我明白。

这不需要超专业的 python 包,因为我需要将它移植到其他一些编码语言。

更新:第二个例子: 如果我有一个数据集,例如

[["Col1","Col2"],
 ["A","B1"],
 ["B1","C1"],
 ["B1,"C2"],
 ["C2,"D"],
 ["A,"B2"]]

我希望:

[["Col1","Col2","Col3","Col4"],
 ["A","B1","C1",""],
 ["A","B1","C2","D"],
 ["A","B2","",""]]

【问题讨论】:

  • 我喜欢您保持其通用性,但您的示例最终可能过于简单化,并产生可能不完全适用的答案。您是否希望您的数据在第一个索引中作为列名提供,而在第二个索引中仅作为值提供?可以这么说,这些价值观是否倾向于在“尾巴”处加入?这可能太模糊了。
  • col3col4 ?他们是从哪里来的?
  • @ParitoshSingh - 好点。索引和列名不如列的顺序重要。应该在尾部和头部连接,因为第一列中的第一项可能不是真正的头部,但实际上是“本地头部”。相反,我需要从某个任意值向前和向后移动。
  • 请用文字准确地解释你在做什么。请通过帖子编辑进行澄清,而不是 cmets。

标签: python recursion transpose self-join


【解决方案1】:

给你想要的结果:

fam = [["Col1","Col2"],["A","B"],["B","C"],["C","D"]]

col, chi, res = [], [], []

for i in fam:
    for ii in i:
        if len(ii) == 1:
            if ii in chi:
                chi.remove(ii)
            chi.append(ii)
        else:
            col.append(ii)

res.append(col)
res.append(chi)

>>>print(res)
>>>[['Col1', 'Col2'], ['A', 'B', 'C', 'D']]

【讨论】:

    【解决方案2】:

    您可以从将每个父级映射到一个子级列表的父子对中构建一个列表字典,通过使用字典键和子级集之间的集合差异来找到顶级父级,使这些顶级父级成为子级的None,这样您就可以从以None 作为最顶层父级的映射dict 开始递归构建连接列表,但在输出连接列表时忽略None

    def join(pairs):
        def _join(parent=None):
            if parent not in tree:
                return [[parent]]
            output = []
            for child in tree[parent]:
                for joined in _join(child):
                    output.append([*([parent] if parent else []), *joined])
            return output
        tree = {}
        children = set()
        for parent, child in pairs:
            tree.setdefault(parent, []).append(child)
            children.add(child)
        for parent in tree.keys() - children:
            tree.setdefault(None, []).append(parent)
        return _join()
    

    所以给定:

    pairs = [
        ["A", "B1"],
        ["B1", "C1"],
        ["B1", "C2"],
        ["C2", "D"],
        ["A", "B2"]
    ]
    

    joined(pairs) 会返回:

    [['A', 'B1', 'C1'], ['A', 'B1', 'C2', 'D'], ['A', 'B2']]
    

    现在,如果您想用空字符串填充列数较少的行,您可以先获取最大列数,然后遍历行以使用足够的空字符串扩展它们以使它们具有相等的列数:

    joined = join(pairs)
    max_columns = max(map(len, joined))
    for path in joined:
        path.extend([''] * (max_columns - len(path)))
    

    joined 会变成:

    [['A', 'B1', 'C1', ''], ['A', 'B1', 'C2', 'D'], ['A', 'B2', '', '']]
    

    请注意,我在您的问题中忽略了诸如 ['Col1', 'Col2'] 之类的列标题,因为它们与问题无关,并且您没有解释 'Col3''Col4' 的来源。

    【讨论】:

      猜你喜欢
      • 2015-04-25
      • 1970-01-01
      • 2017-05-28
      • 1970-01-01
      • 2013-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-31
      相关资源
      最近更新 更多