2013-01-10 85 views
5

Tôi có câu hỏi về việc xóa các từ khóa trùng lặp bằng Python. Tôi đã đọc một loạt bài đăng nhưng vẫn chưa thể giải quyết được. Tôi có file csv sau:Loại bỏ trùng lặp bằng Python

EDIT

Input:

ID, Source, 1.A, 1.B, 1.C, 1.D 
1, ESPN, 5,7,,,M 
1, NY Times,,10,12,W 
1, ESPN, 10,,Q,,M 

Output nên là:

ID, Source, 1.A, 1.B, 1.C, 1.D, duplicate_flag 
1, ESPN, 5,7,,,M, duplicate 
1, NY Times,,10,12,W, duplicate 
1, ESPN, 10,,Q,,M, duplicate 
1, NY Times, 5 (or 10 doesn't matter which one),7, 10, 12, W, not_duplicate 

Nói cách, nếu ID là tương tự, lấy giá trị từ hàng có nguồn "NY Times", nếu ow với "NY Times" có giá trị trống và hàng trùng lặp từ nguồn "ESPN" có giá trị cho ô đó, lấy giá trị từ hàng có nguồn "ESPN". Để xuất, hãy gắn cờ hai dòng gốc làm bản sao và tạo dòng thứ ba.

Để làm rõ một chút nữa, vì tôi cần phải chạy script này trên nhiều tập tin csv khác nhau với tiêu đề cột khác nhau, tôi không thể làm điều gì đó như:

def main(): 
     with open(input_csv, "rb") as infile: 
      input_fields = ("ID", "Source", "1.A", "1.B", "1.C", "1.D") 
      reader = csv.DictReader(infile, fieldnames = input_fields) 
      with open(output_csv, "wb") as outfile: 
       output_fields = ("ID", "Source", "1.A", "1.B", "1.C", "1.D", "d_flag") 
       writer = csv.DictWriter(outfile, fieldnames = output_fields) 
       writer.writerow(dict((h,h) for h in output_fields)) 
       next(reader) 
       first_row = next(reader) 
       for next_row in reader: 
        #stuff 

Bởi vì tôi muốn chương trình để chạy trên hai cột đầu tiên độc lập với bất kỳ cột nào khác trong bảng. Nói cách khác, "ID" và "Nguồn" sẽ nằm trong mọi tệp đầu vào, nhưng phần còn lại của các cột sẽ thay đổi tùy thuộc vào tệp.

Rất cảm kích mọi trợ giúp bạn có thể cung cấp! FYI, "Nguồn" chỉ có thể là: NY Times, ESPN, hoặc Wall Street Journal và thứ tự ưu tiên cho các bản sao là: lấy NY Times nếu có, nếu không có ESPN, nếu không thì hãy lấy Wall Street Journal. Điều này giữ cho mọi tệp đầu vào.

Trả lời

2

Mã bên dưới đọc tất cả các bản ghi vào một từ điển lớn có khóa là mã định danh của chúng và giá trị của nó là từ điển ánh xạ tên nguồn cho toàn bộ hàng dữ liệu. Sau đó, nó lặp lại thông qua từ điển và cung cấp cho bạn đầu ra mà bạn yêu cầu.

import csv 

header = None 
idfld = None 
sourcefld = None 

record_table = {} 

with open('input.csv', 'rb') as csvfile: 
    reader = csv.reader(csvfile) 
    for row in reader: 
     row = [x.strip() for x in row] 

     if header is None: 
      header = row 
      for i, fld in enumerate(header): 
       if fld == 'ID': 
        idfld = i 
       elif fld == 'Source': 
        sourcefld = i 
      continue 

     key = row[idfld] 
     sourcename = row[sourcefld] 

     if key not in record_table: 
      record_table[key] = {sourcename: row, "all_rows": [row]} 
     else: 
      if sourcename in record_table[key]: 
       cur_row = record_table[key][sourcename] 
       for i, fld in enumerate(row): 
        if cur_row[i] == '': 
         record_table[key][sourcename][i] = fld 
      else: 
       record_table[key][sourcename] = row 
      record_table[key]["all_rows"].append(row) 

print ', '.join(header) + ', duplicate_flag' 

for recordid in record_table: 
    rowdict = record_table[recordid] 

    final_row = [''] * len(header) 

    rowcount = len(rowdict) 

    for sourcetype in ['NY Times', 'ESPN', 'Wall Street Journal']: 
     if sourcetype in rowdict: 
      row = rowdict[sourcetype] 
      for i, fld in enumerate(row): 
       if final_row[i] != '': 
        continue 
       if fld != '': 
        final_row[i] = fld 

    if rowcount > 1: 
     for row in rowdict["all_rows"]: 
      print ', '.join(row) + ', duplicate' 

    print ', '.join(final_row) + ', not_duplicate' 
+0

Cảm ơn câu trả lời tuyệt vời. Nó hoạt động rất tốt trên dữ liệu. Xin lỗi vì sự chậm trễ trong phản hồi, tôi muốn làm việc thông qua mã bản thân mình để đảm bảo rằng tôi thực sự hiểu tại sao nó hoạt động. Tôi gặp phải một vấn đề: Nếu một hàng nhất định có cùng giá trị "ID" và "Nguồn", thì tập lệnh hiện tại sẽ chỉ chạy hàng cuối cùng với kết hợp "ID" và "Nguồn" cụ thể đó. Có cách nào để tinh chỉnh mã sao cho tất cả các dòng gốc được sao chép vào đầu ra (với thẻ "trùng lặp" nếu có) VÀ hàng "không trùng lặp" được điền vào để tránh sự cố được đề cập trong nhận xét này không? – user7186

+0

Tôi sẽ thêm một điểm dữ liệu mẫu vào bài đăng ở trên làm bản chỉnh sửa để bạn có thể thấy điều này dễ dàng hơn. Cảm ơn rất nhiều lần nữa! Điều này thực sự hữu ích và tôi đã học được một số tiền tốt để nhập lại nó. – user7186

+0

Trong ví dụ mới ở trên, có hai hàng có "ID" = 1 và "SOURCE" = ESPN. Nếu không có giá trị cho một cột nhất định trong hàng "NY Times" và có giá trị trong cả hai cột của hàng "ESPN", không quan trọng dòng ESPN nào chúng tôi lấy từ đó, chỉ cần chúng tôi nhất quán trên các tập tin. Tuy nhiên, nếu hàng "NY Times" không có giá trị cho một cột cụ thể và một hàng "ESPN" (ESPN A) không có giá trị cho cột đó, hãy lấy từ hàng "ESPN" khác (ESPN B) . Và, nếu ESPN A có giá trị nhưng ESPN B thì không, và hàng "NY Times" thì không, lấy từ ESPN A. – user7186

Các vấn đề liên quan