2014-06-29 35 views
1

我有一個包含許多列的FITS文件。該文件的一個簡化的例子中的一部分是這樣的:通過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是相同的,但列變化從1到4然後列的下一個5個值A和C是相同的,但列 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以及?

+3

你有什麼試過的?你最初的代碼是什麼?什麼不行? SO不是在這裏做你的功課,你應該先試試自己的東西:) – favoretti

+0

@favoretti這不是作業!我試圖使用枚舉,但這並沒有幫助。我也試着用for循環來思考,這並沒有幫助 – ThePredator

+0

@favoretti因爲A和C不相等,即沒有相同的值,我很困惑使用什麼。如果他們是平等的,我可以使用枚舉並說如果A == C,返回len(B) – ThePredator

回答

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分割行,以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] 
+0

我剛剛使用Collections.counter對我的文章進行了編輯,這似乎很容易使用。 WRT給你的答案,列A和C應該排序,因爲使用groupby? – ThePredator

+0

@Srivatsan如果你有600萬行,可能難以分類。權衡是如果你的文件已經被排序了,那麼就不需要在內存中保存一個'Counter'。但是,如果它沒有排序並且條目的順序不重要,那麼使用「計數器」是最簡單的... –

+0

我只想計算每個A和C相等的值的數量並打印一個新的與這些值列。 WRT給你的答案,應該是什麼'輸出'?我應該創建一個txt文件,還是隻能在'output'中提到一個文件名,在執行時由Python – ThePredator

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 
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 
+0

問題是,我的文件有600多萬行!所以我正在尋找一個軟件包,我剛纔碰到了這個名爲collections的軟件包,它有一個叫做counter的子程序,我試圖從現在開始使用 – ThePredator

+0

@Srivatsan你需要存儲'x = len(b) '對於每個'a,c'組合? – Valijon

+0

是的,我需要所有A和C的值相等。即len(b) – ThePredator

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) 
相關問題