0

我的数据文件如下所示:

3.6-band 
6238
Over
0.5678
Over
0.6874
Over
0.7680
Over
0.7834

我想要做的是挑选出最小的浮点数和它正上方的单词并打印这两个值。我不知道我在做什么。我试过了

df=open('filepath')
  for line in df:
    df1=line.split()
    df2=min(df1)

这是我至少尝试隔离最小浮动的尝试。问题是它只是给了我最后的价值。我认为这是 python 不知道从迭代重新开始的问题,但是再次......不知道我在做什么。我试过df2=min(df1.seek(0))没有成功,得到一个错误说no attribute seek。所以这就是我到目前为止所尝试的,我仍然不知道如何打印最小浮动之前的行。建议/帮助/建议将不胜感激,谢谢。

附带说明:此数据文件是具有相似特征的较大数据文件的示例,但“Over”一词也可能是“Under”,这就是我需要打印它的原因。

4

5 回答 5

2

将项目存储在列表、[word,num]对列表中,然后应用于min该列表列表。使用key参数 ofmin指定必须使用哪个项目来比较项目。:

with open('abc') as f:
    lis = [[line.strip(),next(f).strip()] for line in f]
    minn = min(lis, key = lambda x: float(x[1]))
    print "\n".join(minn)
...     
Over
0.5678

这里lis看起来像这样:

[['3.6-band', '6238'], ['Over', '0.5678'], ['Over', '0.6874'], ['Over', '0.7680'], ['Over', '0.7834']]
于 2013-07-07T21:50:13.250 回答
2

您可以使用grouper recipeizip(*[iterator]*2)将线条df分成 2 组。然后,要找到最小的线条,使用min及其key参数来指定用于比较的代理。在这种情况下,对于每一对行,(p, l)我们希望使用第二行的浮点数float(l),作为代理:

import itertools as IT
with open('filepath') as df:
    previous, minline = min(IT.izip(*[df]*2), 
                            key=lambda (p, l): float(l))
    minline = float(minline)
    print(previous)
    print(minline)

印刷

Over

0.5678

石斑鱼食谱的解释:

要了解石斑鱼配方,首先看看如果df是一个列表会发生什么:

In [1]: df = [1, 2]

In [2]: [df]*2
Out[2]: [[1, 2], [1, 2]]

在 Python 中,当您将列表乘以一个正整数时n,您将获得n列表中项目的(浅)副本。因此,[df]*2制作一个包含两个副本的列表df

现在考虑zip(*[df]*2)

*使用的 in具有zip(*...)特殊的含义。它告诉 Python 解压缩*要传递给的 into 参数之后的列表zip。因此,zip(*[df]*2)完全等价于zip(df, df)

In [3]: zip(df, df)
Out[3]: [(1, 1), (2, 2)]

In [4]: zip(*[df]*2)
Out[4]: [(1, 1), (2, 2)]

SaltyCrane 在这里给出了参数解包的更完整的解释

记下正在做什么zipzip(*[df]*2)剥离两个副本的第一个元素(在这种情况下都是 1),并形成元组 (1,1)。然后它剥离两个副本的第二个元素(两个 2),并形成元组 (2,2)。它返回一个包含这些元组的列表。

现在考虑当df是迭代器时会发生什么。迭代器有点像列表,除了迭代器只适用于单次传递。当项目被拉出迭代器时,迭代器永远不能倒带。

例如,文件句柄是一个迭代器。假设我们有一个带有行的文件

1
2
3
4

In [8]: f = open('data')

f您可以通过调用将项目从迭代器中拉出next(f)

In [9]: next(f)
Out[9]: '1\n'

In [10]: next(f)
Out[10]: '2\n'

In [11]: next(f)
Out[11]: '3\n'

In [12]: next(f)
Out[12]: '4\n'

每次调用时next(f),我们都会从文件句柄中获取下一行f. 如果我们next(f)再次调用,我们会得到一个 StopIteration 异常,表明迭代器是空的。

现在让我们看看石斑鱼食谱的表现如何f

In [14]: f = open('data')  # Notice we have to open the file again, since the old iterator is empty

In [15]: [f]*2
Out[15]: 
[<open file 'data', mode 'r' at 0xa028f98>,
 <open file 'data', mode 'r' at 0xa028f98>]

[f]*2给我们一个列表,其中包含同一个迭代器的两个相同副本f

In [16]: zip(*[f]*2)
Out[16]: [('1\n', '2\n'), ('3\n', '4\n')]

zip(*[f]*2)从第一个迭代器中f剥离第一项,然后从第二个迭代器中剥离第一项f但是迭代器f两次都是一样的!而且由于迭代器适合单次通过(您永远无法返回),因此每次剥离一个项目时都会得到不同的项目。每次zip都打电话来剥一个项目。next(f)所以第一个元组是 ('1\n', '2\n'). 同样,zip然后从第一个迭代器中剥离下一项,f从第二个迭代器中剥离下一项f,并形成元组('3\n', '4\n')。因此,zip(*[f]*2)返回 [('1\n', '2\n'), ('3\n', '4\n')]

这就是石斑鱼食谱的全部内容。上面,我选择使用IT.izip而不是zip这样 Python 会返回一个迭代器而不是一个元组列表。如果文件中有很多行,这将节省大量内存。zip和之间的区别在这里IT.izip得到更全面的解释。

于 2013-07-07T21:51:19.650 回答
1

你不能使用:

min(number)

您只能使用:

min(num1, num2)

如果您的文件如下所示:

6238
0.5678
0.6874
0.7680
0.7834

您可以使用以下代码:

Num1 = float(file.readline())

for line in file:
    Num2 = float(line)
    Num1 = min(Num1, Num2)

如果你有"Over"s 那么你可以跳过每一行。

于 2013-07-07T21:50:27.797 回答
0

我在上面看到了一些有趣的解决方案。我会选择这个简单的解决方案。还有一个问题,就是整数也可以这样取。有人对此有解决方案吗?

    df=open('myfile.txt')
    lines=df.readlines()
    minval = 1e99
    for n,line in enumerate(lines):
        try: 
            val=float(line)  # NB! like this, also integers will be taken. 
            if val < minval:  
                minval = val
                i_min  = n  
        except:
            pass
    word = lines[i_min-1]
于 2013-07-07T22:30:43.807 回答
0

您需要读取文件的所有行,可能使用 File.readlines(),或者像您已经拥有的循环,然后为每一行读取数字(如果它是数字)并与“迄今为止最好的”进行比较价值。

看起来你真的不需要 split()。您需要做的是检查每行是否以数字开头。如果是这样,您可以使用 float(line) 获取数字。如果空格引起麻烦,可能是 float(line.strip()) 。如果该行不是以数字开头,请将其保存在临时变量中。如果下一行证明提供的数字低于迄今为止的最佳值,则可以将该临时值复制到一个变量中以用于暂定输出。

于 2013-07-07T21:59:12.737 回答