如何将一个函数映射到一个三层嵌套列表,并保持三层嵌套列表的完整性?

3

我一直在为我的博士研究构建分析工作流,并使用三重嵌套列表来表示我的数据结构,因为我希望它能够扩展到第二和第三级的任意数量的数据。第一级是整个数据集,第二级是数据集中的每个受试者,第三级是每个受试者的每个测量结果的一行。

[dataset]
      |
      [subject]
              |
              [measure1, measure2, measure3]

我正在尝试为每个指标映射一个函数 - 例如将所有点转换为浮点数或用None替换异常值 - 并希望根据它的嵌套返回整个数据集,但我的当前代码:

for subject in dataset:
    for measure in subject:
        map(float, measure)

......结果是正确的,正是我想要的,但问题在于我不知道如何高效地将结果分配回数据集中,或者不会失去嵌套级别。理想情况下,我希望它可以 * 原地 更改测量值,但我不知道怎么做。

您能否建议一种高效和pythonic的方法来解决这个问题?三重嵌套列表是程序中组织数据的愚蠢方式吗?


2
仅供娱乐,您可以不使用列表推导或循环来完成它 - 不要用这种方式 - from itertools import repeat; dataset = map(map, repeat(map), map(repeat, repeat(float)), dataset) - agf
@agf,概念很棒,但值得注意的是它只在Python 3或具有适当导入的情况下起作用。 - Mike Graham
1
@Mike 你是对的 - 在 Python 2 上它是 from itertools import repeat, imap; dataset = map(list, imap(imap, repeat(map), repeat(repeat(float)), dataset)) - agf
4个回答

14

不要就地修改原列表,而是创建一个新的列表

 dataset = [[[float(value) for value in measure] 
                           for measure in subject] 
                           for subject in dataset] 

3
+1 是因为代码的形状反映了结果值的形状。 - SingleNegationElimination
太好了!这个很有效。我原以为我在程序中已经写出了你所描述的内容,但是出现了内存泄漏错误,我认为它是递归的。很高兴能说它不是,非常感谢Mike。 - EmlynC

3

return [[map(float, measure) for measure in subject] for subject in dataset]

您可以返回一个列表而不是直接修改它——这仍然非常高效并保留了您想要的所有信息。(顺便说一句:实际上,这通常比分配给列表索引更快[citation needed],这是其他人在这里建议的方法!)


在内部层中为什么要使用 map 而不是另一个列表推导式? - agf
少打字。我喜欢少打字。我本来想在之后加上列表推导式的版本,但是Mike Graham已经发布了那个版本,如果我也这么做的话,感觉有点像是试图吸收他的答案,你知道的。它们同样有效。事实上,有人可能会认为只使用列表推导式的版本更优雅,因为它使用的概念更少。不过,这种差异并不真正重要,它们基本上是相同的。 - Devin Jeanpierre
所有点都同意。 查看我在问题上的评论,可以找到最不优雅的方法。 - agf
明天我坐下来时会计时!感谢你的回答Devin。我主要选了Mike的答案,因为像TokenMacGuy所说的那样,它看起来更像是正在处理的数据结构,因此更易读和直观。 - EmlynC

2
一个直接的方法就是在原地进行操作:
for subject in dataset:
    for measure in subject:
        for i, elem in enumerate(measure):
            measure[i] = float(elem)

或者,使用切片操作符使用map的结果来原地更新列表

for subject in dataset:
    for measure in subject:
        measure[:] = map(float, measure)

+1,因为我从来没有考虑过使用完整切片进行重新分配。 - agf

2
这应该能完成工作。
for subject in dataset:
    for measure in subject:
        for i, m in enumerate(measure):
            measure[i] = float(m)

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