2015-02-05 54 views
0

我是Python新手,需要閱讀csv文件並保留重複項目的最低價格。 例子:在csv文件中保留重複項目的最低價格

輸入文件:

name, link, price, category 
item1, http://example.com/item1, 29.30, cat1 
item2, http://example.com/item2, 22, cat2 
item1, http://example.com/item1, 19.90, cat1 

輸出文件:

name, link, price, category 
item2, http://example.com/item2, 22, cat2 
item1, http://example.com/item1, 19.90, cat1 

這裏是我到目前爲止的代碼:

f1 = csv.reader(open('input.csv', 'rb'), delimiter=',') 
    writer = csv.writer(open("output.csv", "wb")) 
    name = set() 
    for row in f1: 
     if row[0].lower() not in (i.lower() for i in name): 
      writer.writerow(row) 
      name.add(row[0]) 

我可以用這個代碼刪除重複的,但我需要幫助,以保持物品的最低價格。

謝謝!

回答

1

可以使用dict.get與inf默認值,檢查是否存儲的值當前價格低於我們遇到然後相應地更新當前。最後寫作從dict.items返回的元組。如果需要,我們也可以使用集合保存文件順序。

import csv 
from collections import OrderedDict 

d = OrderedDict() # keep the order 

with open('in.csv', 'r') as f1, open("output.csv", "w") as out: 
    r = csv.reader(f1,delimiter=",") 
    header = next(r) # store header 
    writer = csv.writer(out,delimiter=",") 
    for row in r: 
     price = float(row[2]) 
     # first check price will be less than than inf so we will add the key/value 
     if d.get(row[2], float("inf")) > price: 
      d[row[0]] = row 
    writer.writerow(header) # write header 
    for tup in d.values(): # write updated items 
     writer.writerow(tup) 

輸出:

name, link, price, category 
item1, http://example.com/item1, 19.90, cat1 
item2, http://example.com/item2, 22, cat2 

如果次序是不相關使用defaultdict和分鐘:

import csv 
from collections import defaultdict 

d = defaultdict(list) # keep the order 
with open('in.csv', 'r') as f1, open("output.csv", "w") as out: 
    r = csv.reader(f1,delimiter=",") 
    header = next(r) # store header 
    writer = csv.writer(out,delimiter=",") 
    for row in r: 
     d[row[0]].append(row) 
    writer.writerow(header) # write header 
    for k,v in d.items(): # write updated items 
     writer.writerow(min(v,key=lambda x:float(x[2]))) 
+0

嘿@Padraic,我很抱歉,但我忘了提及在我的輸入文件中有兩個其他列。 coloumns:名稱,鏈接,價格,類別 我認爲解決方案會因此而改變,對嗎?對不起。 – bleroy 2015-02-05 18:25:20

+0

你只想要兩個? – 2015-02-05 18:26:34

+0

不,我希望輸出的格式與輸入相同:名稱,鏈接,價格,類別 – bleroy 2015-02-05 18:27:32

0

您可以在以下由mu提供的解決方案中縮短使用dict.setdefault的for循環。 dict.setdefault如果密鑰不存在,則爲密鑰設置值,否則保持該值不變。它返回當前值是否更改爲保持不變。

for row in f1: a = names.setdefault(row[0],row[1]) if row[1]<a: names[row[0]] = row[1]

0

這是微不足道在大熊貓:

import pandas as pd 

df = pd.read_csv('in_csv') 
df.groupby('name').min() 
0

csv文件列:name, link, price, category

import itertools, operator 
data = list() 
new_data = list() 
name = operator.itemgetter(0) 
name_price = operator.itemgetter(0,2) 

將標題與數據分開。

with open('data.txt') as f: 
    header = f.next() 
    for line in f: 
     data.append(line.strip().split(',')) 

data是一個列表的列表 - [[name, link, price, category], ...]

上名

排序data第一和第二價格。

data.sort(key = name_price) 

使用itertools.groupby到GROUP BY名,從各組採取的第一項和格式化,然後將其保存到一個新的列表。

for key, group in itertools.groupby(data, name): 
    # the first item in the group has the lowest price 
    lowest_price = list(group)[0] 
    lowest_price = ','.join(lowest_price) + '\n' 
    new_data.append(lowest_price) 

header和```new_data`寫入文件。

with open('new_data.txt', 'wb') as f: 
    f.write(header) 
    f.writelines(new_data) 

編輯爲了解更多字段。

+0

這是'n日誌n'而不是線性使用字典 – 2015-02-05 20:04:21

+0

@PadraicCunningham,你說得很對。這有不止一次傳遞數據的缺點 - 但它非常可讀。如果數據大小不是太大,那麼它應該沒關係....'''過早優化...'''以及所有這些。我在OP的帖子中沒有看到效率規格。歡呼,對我有一個品脫。 – wwii 2015-02-05 20:10:29

+0

是的,但值得指出的可能會遇到問題,並希望有效的解決方案的任何人。 csv模塊也非常適合這個問題 – 2015-02-05 20:15:05