2016-09-28 11 views
-2

2つのcsvファイルをマージして、重複したレコードを保持しようとしています。各ファイルには一致するレコードがあり、1つのファイルには重複レコード(異なるテストスコアの学生ID)があり、1つのファイルには他のファイルに一致する学生レコードがない可能性があります。次のコードは、重複したレコードが存在する場合、2番目のレコードのみがマージされたファイルに書き込まれている場合に期待どおりに動作します。私は多くのスレッドを見て、重複を削除するすべてのアドレスが、私は重複したレコードを保持する必要があります。2つのCSVファイルをマージする重複を維持する

import csv 
from collections import OrderedDict 
import os 

cd = os.path.dirname(os.path.abspath(__file__)) 

fafile = os.path.join(cd, 'MJB_FAScores.csv') 
testscores = os.path.join(cd, 'MJB_TestScores.csv') 

filenames = fafile, testscores 
data = OrderedDict() 
fieldnames = [] 
for filename in filenames: 
    with open(filename, 'r') as fp: 
     reader = csv.DictReader(fp) 
     fieldnames.extend(reader.fieldnames) 
     for row in reader: 
      data.setdefault(row['Student_Number'], {}).update(row) 
fieldnames = list(OrderedDict.fromkeys(fieldnames)) 
with open('merged.csv', 'w', newline='') as fp: 
    writer = csv.writer(fp) 
    writer.writerow(fieldnames) 
    for row in data.values(): 
     writer.writerow([row.get(fields, '') for fields in fieldnames]) 

fafile:

Student_Number Name Grade Teacher FA1 FA2 FA3 
65731 Ball, Peggy 4 Bauman, Edyn 56 45 98 
65731 Ball, Peggy 4 Bauman, Edyn 32 323 232 
85250 Ball, Jonathan 3 Clarke, Mary 65 77 45 
981235 Ball, David 5 Longo, Noel 56 89 23 
91851 Ball, Jeff 0 Delaney, Mary 83 45 42 
543 MAX 2 Phil 77 77 77 
543 MAX 2 Annie 88 888 88 
9844 Lisa 1 Smith, Jennifer 43 44 55 

testscores:

Student_Number Name Grade Teacher MAP Reading MAP Math FP Level DSA LN DSA WW DSA SJ DSA DC 
65731 Ball, Peggy 4 Bauman, Edyn 175 221 A 54 23 78 99 
72941 Ball, Amanda 4 Bauman, Edyn 201 235 J 65 34 65 
85250 Ball, Jonathan 3 Clarke, Mary 189 201 L 34 54 
981235 Ball, David 5 Longo, Noel 225 231 D 23 55 
91851 Ball, Jeff 0 Delaney, Mary 198 175 C 
65731 Ball, Peggy 4 Bauman, Edyn 200 76 Y 54 23 78 99 
543 MAX 2 Phil 111 111 Z 33 44 55 66 
543 MAX 2 Annie 222 222 A 44 55 66 77 

電流出力:

Student_Number Name Grade Teacher FA1 FA2 FA3 MAP Reading MAP Math FP Level DSA LN DSA WW DSA SJ DSA DC 
65731 Ball, Peggy 4 Bauman, Edyn 32 323 232 200 76 Y 54 23 78 99 
85250 Ball, Jonathan 3 Clarke, Mary 65 77 45 189 201 L 34 54 
981235 Ball, David 5 Longo, Noel 56 89 23 225 231 D 23 55 
91851 Ball, Jeff 0 Delaney, Mary 83 45 42 198 175 C 
543 MAX 2 Annie 88 888 88 222 222 A 44 55 66 77 
72941 Ball, Amanda 4 Bauman, Edyn    201 235 J 65 34 65 
9844 Lisa 1 Smith, Jennifer 43 44 55 

所望の出力:

Student_Number Name Grade Teacher FA1 FA2 FA3 MAP Reading MAP Math FP Level DSA LN DSA WW DSA SJ DSA DC 
65731 Ball, Peggy 4 Bauman, Edyn 32 323 232 200 76 Y 54 23 78 99 
65731 Ball, Peggy 4 Bauman, Edyn 56 45 98 175 221 A 54 23 78 99 
85250 Ball, Jonathan 3 Clarke, Mary 65 77 45 189 201 L 34 54 
981235 Ball, David 5 Longo, Noel 56 89 23 225 231 D 23 55 
91851 Ball, Jeff 0 Delaney, Mary 83 45 42 198 175 C 
543 MAX 2 Annie 88 888 88 222 222 A 44 55 66 77 
543 MAX 2 Phil 77 77 77 111 111 Z 33 44 55 66 
72941 Ball, Amanda 4 Bauman, Edyn    201 235 J 65 34 65 
9844 Lisa 1 Smith, Jennifer 43 44 55 
+1

コードは 'KeyError例外を生成します。 – martineau

+0

マージをどのように行うかを明確にしてください。たとえば、生徒ID「65731」の各ファイルに合計4つのレコードが2つありますが、目的の出力には2つしかありません。なぜ4人すべてが守られなかったのですか? – martineau

+0

基本的には、testscoresファイルからのデータは、Student_Number上のファイル・マッチングに水平に追加する必要があります。各ファイルには、さまざまなデータセットが含まれており、すべてのテストスコアを各学生にまとめます。一部の生徒はテストを2回受けるか、まったく受けないので、各ファイルに0,1つ以上のレコードがある場合があります。最終ファイルには、Student_Number、Name、Grade、Teacher、FA1、FA2、FA3、MAP Reading、Map Math、FP Level、DSA LN、DSA WW、DSA SJ、DSA DCの各列が必要です。生徒がファイールでレコードを持っていないが、2つのテストがある場合は、「FAx」フィールドが空の2行のデータが必要です – PBall

答えて

0

あなたは両方のファイルからの学生のID(キー)とそのレコード(値)を格納するOrderedDictを使用しています。

これは微妙な意味合いを持っている:dictのキーは一意であるため、新たな学生IDエントリは、前のファイルから古い重複学生ID辞書エントリに置き換えられます。

mergeファイルに1つのファイルから読み込んだ直後にエントリを書き込むことを検討することがあります。その後、dictはクリアされ、次のファイルはに再利用されます。dict。これにより、の衝突の交換のstudentIDsの回避に役立ちます。

for row in reader: 
    new_record = dict(row) 
    records = data.setdefault(row['Student_Number'], []) 
    for record in records: 
     new_record.update(record) # preserve old values 
     record = copy.copy(new_record) 
    new_record.update(dict(row)) # to preserve original values 
    records.append(new_record) 

書くときに、あなたがより深く、今一歩を行かなければならない:あなたは次の操作を行うことができ、あなたの内側のループのために

0

for rows in data.values(): 
    for row in rows: 
     writer.writerow(row) 

A最初は「インポートコピー」を追加します。私は私の頭からそれを書いた、いくつかの微調整が必​​要な場合があります。

基本的にこれは、古い値を新しいもので更新し、更新された新しいレコードをリストの末尾に追加する(別の収集されたデータがすべて新しいレコードに追加される)リスト形式でレイヤーを追加します。それを書くときには、一層深く進む必要があります。

0

私は個人的にあなたがpandas.DataFrame.from_csv('filename')を使用して、両方のCSV用データフレームを作成し、具体的DataFrame.append

まず、このような何かのためにPandasを使用します。

次に、DataFramesを追加してください:myDataFrame.append(otherDataframe)

最後に結果をto_csv()で出力します。

は一緒にすべてを置く: '([Student_Number']、{}更新(行)ライン `data.setdefault行)にStudent_Number'``:

Code snippet