1

假设我有许多值:(左列只是值计数:1、2、3 等;右列是实际值)

1 5.2
2 1.43
3 3.54
4 887
5 0.35

我想要做的是将值从减小到增加(自上而下)重新排序,然后我想让 python 遍历这些值并继续选择这些值(稍后用作输出)直到它遇到处于或高于某个阈值的值。例如:

5 0.35
2 1.43
3 3.54
1 5.2
4 887

比如说,我的阈值是 5.0,所以在这里我希望程序丢弃 1 和 4(高值)并给出 5、2 和 3 作为输出以及它们的相应值。我希望这是有道理的。如果(无论出于何种原因)我的阈值只允许 2 个值,那么作为一个更棘手的技巧,我希望它忽略所有内容并给出类似“未找到值”的内容。

它们所在的文件我将从中提取它们(值和计数)大致如下所示:

  ID  some: value  another: value another: value another: value another: value another: value 1: 5.2

等等,上面提到的每个值都对应于文件中的一个新行。所以我感兴趣的东西将分别位于第 x 行、第 14 列和第 15 列。

实际的行看起来像这样:

Mod# 2 11494    Chi^2:  1.19608371367   Scale:  0.567691651772  Tin:    1499    Teff:   3400    Luminosity:     568.0   L   M-dot: 4.3497e-08   Tau: 2.44E-01   Dust composition: Fe    IRx1:   0.540471121182

我对 IRx1 及其后的价值感兴趣。

4

2 回答 2

4

假设您的文件每行有一个数字:

threshold = 5
with open('path/to/file') as infile:
    numbers = [float(line.strip()) for line in infile]
numbers.sort(reverse=True)
bigger = list(itertools.takewhile(lambda n: n<threshold, numbers))

如果您的文件如下所示:

1 5.2
2 1.43
3 3.54
4 887
5 0.35

并且您希望输出为set([2,3,5]),然后:

with open('path/to/file') as infile:
    numbers = dict([float(i) for i in line.strip()] for line in infile)
lines = sorted(numbers, key=numbers.__getitem__, reverse=True)
answer = list(itertools.takewhile(lambda n: numbers[n]<threshold, lines))

给定一个看起来像这样的文件:

Mod# 2 11494    Chi^2:  1.19608371367   Scale:  0.567691651772  Tin:    1499    Teff:   3400    Luminosity:     568.0   L   M-dot: 4.3497e-08   Tau: 2.44E-01   Dust composition: Fe    IRx1:   0.540471121182

如果有一个制表符 ( \t) 分隔11494Chi^2,下面的脚本应该可以工作:

def takeUntil(fpath, colname, threshold):
    lines = []
    with open(fpath) as infile:
        for line in infile:
            ldict = {}
            firsts = line.split('\t', 2)
            ldict[firsts[0] = float(firsts[1])
            splits = firsts[2].split('\t')
            ldict.update(dict(zip(firsts, itertools.islice(firsts, 1, len(firsts)))))
            lines.append(ldict)
    lines.sort(reverse=True, key=operator.itemgetter(colname))
    return [row['Mod#'] for row in itertools.takewhile(lambda row: row[colname]<threshold, lines)]

使用该功能,您应该能够指定要检查哪个列的值低于阈值。尽管此算法确实具有更高的空间复杂度(使用的 RAM 比绝对必要的更多),但您应该能够lines在读取文件后编组/腌制并从那里继续进行后续运行。如果您有一个需要一段时间来处理的巨大输入文件(我怀疑您可能有),这将特别有用

于 2013-07-10T03:22:14.147 回答
4

以下解决方案假定数据是作为元组列表读入的。

前任:

[(1,5.2),
(2,1.43),
(3,3.54),
(4,887),
(5,0.35)]

将是问题中样本数据的列表。

def cutoff(threshold, data):
    sortedData = sorted(data, key=lambda x: x[1])
    finalList = filter(lambda x: x[1] < threshold, sortedData)
    return finalList if len(finalList) > 2 else 'No values found'

该函数的第一行按元组第二位的值对列表进行排序。

然后,该函数的第二行过滤该结果列表,以便仅保留值低于阈值的元素。

如果第三行包含两个以上的元素,则返回结果排序列表,否则返回“未找到值”,这应该完成您想要做的事情,减去文件输入。

于 2013-07-10T03:28:05.497 回答