【问题标题】:How to I extract floats from a file in Python?如何从 Python 中的文件中提取浮点数?
【发布时间】:2011-01-18 23:13:34
【问题描述】:

所以,我有一个看起来像这样的文件:

# 3e98.mtz MR_AUTO with model 200la_.pdb
SPACegroup HALL P 2yb #P 1 21 1
SOLU SET RFZ=3.0 TFZ=4.7 PAK=0 LLG=30
SOLU 6DIM ENSE 200la_ EULER 321.997 124.066 234.744 FRAC -0.14681 0.50245 -0.05722
SOLU SET RFZ=3.3 TFZ=4.2 PAK=0 LLG=30
SOLU 6DIM ENSE 200la_ EULER 329.492 34.325 209.775 FRAC 0.70297 0.00106 -0.24023
SOLU SET RFZ=3.6 TFZ=3.6 PAK=0 LLG=30
SOLU 6DIM ENSE 200la_ EULER 177.344 78.287 187.356 FRAC 0.04890 0.00090 -0.57497

遍历此文件并仅提取浮点数的最佳方法是什么?

在这种情况下,“最佳”方案是仅提取类似于“321.997”的数字(它们是病毒细胞结构坐标)并将它们添加到列表中。在我正在查看的每个文件中,每行都有 6 个这样的数字。提取这些数字后,我可以在我已经编写的方法中使用该列表来计算新坐标,以旋转单元结构以匹配数据集中的其他数据。

【问题讨论】:

  • 在什么意义上最好?你的限制或目标是什么?您的输入可以有多大?您是否需要将解决方案移植到旧版本的 Python 中?你期待大量的失败还是大量的成功?您是否希望将“0e0”之类的东西视为浮点数?那么“1,100.0”呢?文化问题呢?除非您更详细地描述您的问题,否则不可能知道什么最适合您的具体情况。
  • 不是作业,我发誓!这是一个从名为 Phaser 的程序获取 URL 编码输出的项目,并使用浮点值计算单元结构的新 x、y 和 z 坐标。
  • @stephenjahl:如果不是家庭作业,请提供一些有关您要优化的内容的背景信息。正如@Mark Byers 指出的那样,没有背景就无法解释“最佳”。家庭作业没有背景。如果您有一些背景知识,请提示所说的“最佳”是什么意思。
  • 简单! "def filterFloats(): return []",因为该列表中没有浮点数,只有字符串...
  • @stephenjahl:请使用您的最佳方案信息更新问题。请不要评论您拥有的问题。请更正并澄清问题。然后删除评论。没有人会阅读一长串 cmets 来理解您的问题。

标签: python list floating-point loops


【解决方案1】:

这是一种方法。

def floats( aList ):
    for v in aList:
        try:
            yield float(v)
        except ValueError:
            pass

a = list( floats( [....] ) )

【讨论】:

  • 这也会提取整数,不是吗?
  • 如果要从列表中排除整数,我想是“如果”。在 try 块中的 in v" 子句就可以了。
  • @chradcliffe。不,您不需要任何 if 声明。首先尝试使用int() 进行转换。如果成功,通过。如果int 转换失败,请尝试使用float 进行转换。您不想在内置函数之外添加任何逻辑。示例 int('12.') 引发 ValueError
【解决方案2】:
floats = []
all = ['#', '3e98.mtz', 'MR_AUTO', 'with', 'model', '200la_.pdb', 'SPACegroup', 'HALL', 'P', '2yb', '#P', '1', '21', '1', 'SOLU', 'SET', 'RFZ=3.0', 'TFZ=4.7', 'PAK=0', 'LLG=30', 'SOLU', '6DIM', 'ENSE', '200la_', 'EULER', '321.997', '124.066', '234.744', 'FRAC', '-0.14681', '0.50245', '-0.05722', 'SOLU', 'SET', 'RFZ=3.3', 'TFZ=4.2', 'PAK=0', 'LLG=30', 'SOLU', '6DIM', 'ENSE', '200la_', 'EULER', '329.492', '34.325', '209.775', 'FRAC', '0.70297', '0.00106', '-0.24023', 'SOLU', 'SET', 'RFZ=3.6', 'TFZ=3.6', 'PAK=0', 'LLG=30', 'SOLU', '6DIM', 'ENSE', '200la_', 'EULER', '177.344', '78.287', '187.356', 'FRAC', '0.04890', '0.00090', '-0.57497']
for element in all:
    try:
        floats.append(float(element))
    except ValueError:
        pass

【讨论】:

  • 很好的接触——将浮动附加到列表中可以保持浮动有用。
【解决方案3】:
def is_float(i):
        try:
            float(i)
            return True
        except ValueError:
            return False


L=['#', '3e98.mtz', 'MR_AUTO', 'with', 'model', '200la_.pdb', 'SPACegroup', 'HALL', 'P', '2yb', '#P', '1', '21', '1', 'SOLU', 'SET', 'RFZ=3.0', 'TFZ=4.7', 'PAK=0', 'LLG=30', 'SOLU', '6DIM', 'ENSE', '200la_', 'EULER', '321.997', '124.066', '234.744', 'FRAC', '-0.14681', '0.50245', '-0.05722', 'SOLU', 'SET', 'RFZ=3.3', 'TFZ=4.2', 'PAK=0', 'LLG=30', 'SOLU', '6DIM', 'ENSE', '200la_', 'EULER', '329.492', '34.325', '209.775', 'FRAC', '0.70297', '0.00106', '-0.24023', 'SOLU', 'SET', 'RFZ=3.6', 'TFZ=3.6', 'PAK=0', 'LLG=30', 'SOLU', '6DIM', 'ENSE', '200la_', 'EULER', '177.344', '78.287', '187.356', 'FRAC', '0.04890', '0.00090', '-0.57497']
print filter(is_float,L)

【讨论】:

    【解决方案4】:

    如果您以不鼓励回答者检查其结构的方式显示您的输入,并且您提出诸如“如何仅提取浮点数”之类的问题,并隐藏诸如“在我正在查看的每个文件中”之类的有用信息,在 cmets 中每行有 6 个这样的数字”,您将得到准确的答案,提供您所要求的内容:包含 3 个虚假数字(1.0、21.0 和 1.0)的“浮点数”列表 在列表的前面。

    如果您以更合适的方式显示数据,例如:

    alist = [
        '#', '3e98.mtz', 'MR_AUTO', 'with', 'model', '200la_.pdb', 'SPACegroup', 'HALL', 'P', '2yb',
        '#P', '1', '21', '1', 
        'SOLU', 'SET', 'RFZ=3.0', 'TFZ=4.7', 'PAK=0', 'LLG=30', 'SOLU', '6DIM', 'ENSE', '200la_',
            'EULER', '321.997', '124.066', '234.744', 'FRAC', '-0.14681', '0.50245', '-0.05722',
        'SOLU', 'SET', 'RFZ=3.3', 'TFZ=4.2', 'PAK=0', 'LLG=30', 'SOLU', '6DIM', 'ENSE', '200la_',
            'EULER', '329.492', '34.325', '209.775', 'FRAC', '0.70297', '0.00106', '-0.24023',
        'SOLU', 'SET', 'RFZ=3.6', 'TFZ=3.6', 'PAK=0', 'LLG=30', 'SOLU', '6DIM', 'ENSE', '200la_', 
            'EULER', '177.344', '78.287', '187.356', 'FRAC', '0.04890', '0.00090', '-0.57497'
        ]
    

    人们可能会注意到结构(EULER 后跟三个数字,然后 FRAC 后跟三个数字)重复并执行“哦,他的文件中每行六个数字”并返回一些更有用的建议,例如:

    从头开始,告诉我们你的文件结构是什么。可能有更好的方法来获取您的信息,而不是将您的文件粉碎成一个字符串列表,然后尝试从中恢复。

    更新同时,这是一个使用数据和 cmets 中明显结构的答案,如果结构有变化,则更易于调试:

    TAG0 = 'EULER'
    TAG1 = 'FRAC'
    
    def extract_rows(tokens):
        pos = 0
        while True:
            try:
                pos = tokens.index(TAG0, pos)
            except ValueError:
                return
            assert pos + 8 <= len(tokens)
            assert tokens[pos+4] == TAG1
            yield (
                tuple(map(float, tokens[pos+1:pos+4])),
                tuple(map(float, tokens[pos+5:pos+8])),
                )
            pos += 8
    
    for rowx, row in enumerate (extract_rows(alist)):
        print rowx, 'TAG0', row[0]
        print rowx, 'TAG1', row[1]
    

    结果:

    0 TAG0 (321.99700000000001, 124.066, 234.744)
    0 TAG1 (-0.14681, 0.50244999999999995, -0.05722)
    1 TAG0 (329.49200000000002, 34.325000000000003, 209.77500000000001)
    1 TAG1 (0.70296999999999998, 0.00106, -0.24023)
    2 TAG0 (177.34399999999999, 78.287000000000006, 187.35599999999999)
    2 TAG1 (0.048899999999999999, 0.00089999999999999998, -0.57496999999999998)
    

    更新 2 根据您的示例文件,以下简单代码(未经测试)应该可以满足您的需求:

    for line in open('my_file.txt'):
        row = line.split()
        if row[0] == 'SOLU' and row[1] == '6DIM' and row[4] == 'EULER' and row[8] == 'FRAC':
            euler = map(float, row[5:8])
            frac = map(float, row[9:12])
            do_something_with(euler, frac)
    

    注意:您正在寻找的是“所有浮点数”(无论如何都会忽略RFZ=3.0 TFZ=4.7 中的浮点数!),这只是一个巧合。您拥有的是一个带有 STRUCTURE 的文件:两种类型的 SOLU 记录,并且您想要在 SOLU 6DIM 记录中出现在 EULER 之后的 3 个数字和 FRAC 之后的 3 个数字。您不需要所有这些数字的列表,并且必须将它们再次拆分为(3 个 EULER 数字和 3 个 FRAC 数字)乘以 N。

    【讨论】:

    • 感谢您的提示!我可以通过阅读文件来使用这种方法,而不是将我的文件拆分成大量的字符串吗?即for line in file?更新:我已更新以包含文件本身,而不是字符串列表。
    猜你喜欢
    • 2021-09-25
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    • 2017-01-19
    • 2018-02-10
    相关资源
    最近更新 更多