2012-07-20 115 views
1

匹配行我得到每兩個文件包含以 「時間」 列,一個與 「ID」 是這樣的:減去在python

文件1:

time  id 
11.24 1 
11.26 2 
11.27 3 
11.29 5 
11.30 6 

文件2:

time  id 
11.25 1 
11.26 3 
11.27 4 
11.31 6 
11.32 7 
11.33 8 

我試圖做一個python腳本,可以減去相互匹配的id行的時間。這些文件的長度不同。

我試過使用set(id's of file 1) & set(id's of file 2)來獲得匹配的id,但現在我卡住了。任何幫助將不勝感激,謝謝。

+1

這個特定情況下的輸出應該如何? – eumiro 2012-07-20 10:36:17

回答

2

Python集不支持對元素進行排序。我想將數據存儲作爲字典

file1 = {1:'11:24', 2:'11:26', ... etc} 
file2 = {1:'11:25', 3:'11:26', ... etc} 

以上(根據您的需要或聯合)鍵的交叉循環做減法(基於時間或基於數學)。

+0

詞典不支持排序 – entropy 2012-07-20 23:46:34

+0

@entropy yes但這在這裏並不重要,因爲循環只能通過鍵的交集(完全像您在回答中編碼的那樣)。 – Meitham 2012-07-21 12:49:30

0

這是一個有點老派。看看使用collections模塊的默認字典作爲更優雅的方法。

這將適用於任何數量的文件,我已經命名爲我的f1,f2等。一般的想法是處理每個文件併爲每個id建立一個時間值列表。文件處理完成後,遍歷字典,按照當前值(通過值列表中的reduce)減去每個值。

from operator import sub 

d = {} 
for fname in ('f1','f2'): 
    for l in open(fname): 
     t, i = l.split() 
     d[i] = d.get(i, []) + [float(t)] 

results = {} 
for k,v in d.items(): 
    results[k] = reduce(sub, v) 

print results 
{'1': -0.009999999999999787, '3': 0.009999999999999787, '2': 11.26, '5': 11.29, '4': 11.27, '7': 11.32, '6': -0.009999999999999787, '8': 11.33} 

更新

如果你想只包括與多個值這些ID:

results = {} 
for k,v in d.items(): 
    if len(v) > 1: 
     results[k] = reduce(sub, v) 
+0

看起來像一個非常好的解決方案。但是,如果我只想保留具有匹配ID的行,該怎麼辦? – user1540477 2012-07-20 11:25:00

+0

@ user1540477:只需檢查最後一個循環中值列表的長度是否大於1。查看更新的答案。 – mhawke 2012-07-22 23:43:43

0

您可以使用此作爲基礎(而不是把'11 0.24' 爲一個浮點數,我想你想適應幾小時/分鐘或分鐘/秒)...你可以使用defaultdict有效地結合並減去匹配鍵。

只要你可以得到你的數據轉換成這樣的格式:

f1 = [ 
    [11.24, 1], 
    [11.26, 2], 
    [11.27, 3], 
    [11.29, 5], 
    [11.30, 6] 
] 

f2 = [ 
    [11.25, 1], 
    [11.26, 3], 
    [11.27, 4], 
    [11.31, 6], 
    [11.32, 7], 
    [11.33, 8] 
] 

然後:

from collections import defaultdict 
from itertools import chain 

dd = defaultdict(float) 
for k, v in chain(
    ((b, a) for a, b in f1), 
    ((b, -a) for a, b in f2)): # negate a 

    dd[k] += v 

結果:

{1: -0.009999999999999787, 
2: 11.26, 
3: 0.009999999999999787, 
4: -11.27, 
5: 11.29, 
6: -0.009999999999999787, 
7: -11.32, 
8: -11.33} 

對於比賽只

matches = dict((k, v) for v, k in f1) 
d2 = dict((k, v) for v, k in f2) 

for k, v in matches.items(): 
    try: 
     matches[k] = v - d2[k] 
    except KeyError as e: 
     del matches[k] 

print matches 
# {1: -0.009999999999999787, 3: 0.009999999999999787, 6: -0.009999999999999787} 
+0

似乎是一個非常好的解決方案。但是,如果我只想保留具有匹配ID的行,該怎麼辦? – user1540477 2012-07-20 11:24:50

+0

@ user1540477更新爲只匹配 – 2012-07-20 11:40:39

3

列表內涵可以做的伎倆很容易:

#read these from file if you want to, included in this form for brevity 
F1 = {1: 11.24, 2: 11.26, 3:11.27, 5:11.29, 6:11.30} 
F2 = {1:11.25, 3:11.26, 4:11.27, 6:11.31, 7:11.32, 8:11.33} 

K1 = set(F1.keys()) 
K2 = set(F2.keys()) 

result = dict([ (k, F1[k] - F2[k]) for k in (K1 & K2)]) 
print result 

這將輸出:

{1: -0.009999999999999787, 3: 0.009999999999999787, 6: -0.009999999999999787} 

編輯:mhawke指出,最後一行可以讀取:

result = {k: F1[k] - F2[k]) for k in (K1 & K2)} 

我忘記了所有關於字典的理解。

+1

+1:很好的解決方案。您還可以在最後一步中使用詞典理解:'(k1&K2)}中的結果= {k:F1 [k] - F2 [k]}' – mhawke 2012-07-22 23:58:48

+0

感謝您的支持,將它添加到答案中 – entropy 2012-07-23 09:37:07