按FITS文件中多列中的值聚合表行

时间:2014-06-29 11:27:59

标签: python fits pyfits

我有一个包含许多列的FITS文件。该文件的简化示例的一部分如下所示:

    A      B      C
   100     1      90
   100     2      90
   100     3      90
   100     4      90
   211     40     70
   211     41     70
   211     42     70
   211     43     70
   211     44     70

如果您在此处注意到, A和C 列的前四行是相同的,但 B 列从1到4不等。然后接下来的5个值列 A和C 相同,但 B 列从40到44不等。

我想做的是,编写一个创建如下文件的程序:

   A      B     C
  100     4     90
  211     5     70

也就是说, B列应该包含A列和C列相同的值的数量!

我想知道在Python中如何做到这一点。它不一定需要处理FITS文件,如果有一些例程无法在FITS文件中使用,我也可以将其转换为ASCII格式。

到目前为止我尝试过:

我遇到了一个名为Collections的例程,它有一个名为Counter的子例程,它计算列表中相等的值并返回它们。

我试过了:

import collections
counter = collections.Counter(a)
counts = counter.values()

但这只会让我在 A 列中的值相等。有人可以告诉我如何使用此例程将这些值与列 C 进行比较吗?

4 个答案:

答案 0 :(得分:5)

我会选择这样的东西......:

from itertools import groupby
from operator import itemgetter

with open('input') as fin, open('output', 'w') as fout:
    fout.write(next(fin, ''))
    rows = (line.split() for line in fin)
    for k, g in groupby(rows, itemgetter(0, 2)):
        fout.write('{} {} {}\n'.format(k[0], sum(1 for _ in g), k[1]))
  • 直接写出标题......
  • 构建生成器以生成按空格分割的行
  • 使用itertools.groupby分组第一列和第三列
  • 计算g中出现的次数以获得组的长度
  • 写出所需格式的行......

如果论坛不连续且您应该计为一个,您也可以使用collections.Counter,您可以使用以下内容替换groupby

counts = Counter((row[0], row[2]) for row in rows)
for k, v in counts.iteritems():
    fout.write('{} {} {}\n'.format(k[0], v, k[1]) # or even...
            # print >> fout, k[0], v, k[1] 

答案 1 :(得分:3)

这似乎按预期工作:

out = [["A", "B", "C"]]

# Safely handle opening the file
with open("demo.txt") as f:
    a_count = 1
    prev_a = None

    for i, line in enumerate(f):
        a, b, c = [int(x) for x in line.split()]

        if i != 0:
            if prev_a == a and prev_c == c:
                a_count += 1
            else:
                out.append([prev_a, a_count, prev_c])
                a_count = 1

        # Keep track of our last results
        prev_a, prev_c = a, c

    # Collect the final line counts
    if prev_a:
        out.append([prev_a, a_count, prev_c])

# Pretty-print our results
for line in out:
    print "{0: ^6}{1: ^6}{2: ^6}".format(*line)

答案 2 :(得分:0)

您应该在问题中添加一些代码,以显示您尝试过的内容。如果他们看不到你的尝试,人们通常不会想要帮助很多 - 包括我自己。

作为逻辑方面的暗示(基本。有更简洁的方法):

尝试使用由A列和C列编号组成的密钥。然后,每当A和C相同时,在字典中搜索具有该组合的键,如果找到,则将值加1,如果找不到,则添加新元素。

使用你的例子(伪代码 - 所以你有事情要做:P)

if "100-90" in array:  // Checking if the element is in the array
  array["100-90"] += 1  // Adds one to an existing element
else
  array["100-90] = 1  // Adds a new element into array

答案 3 :(得分:0)

试试这个:

lines = """100 1 90
100 2 90
100 3 90
100 4 90
211 40 70
211 41 70
211 42 70
211 43 70
211 44 70""".split("\n")

count = 0
oldA = oldB = oldC = None
for line in lines:

    a,b,c = line.split(" ")
    if None in [oldA, oldB, oldC]:
        oldA,oldB,oldC = a,b,c

    if oldA == a and oldC == c:
        count +=1

    else:
        print oldA,count,oldC
        count = 1
        oldA, oldB, oldC = a,b,c

print oldA,count,oldC