0

複数のCSVファイルをPythonで比較し、レポートを出力したいと考えています。比較するCSVファイルの数はさまざまなので、ディレクトリからリストを取得してもらいます。各CSVには2つの列があります。1つ目は市外局番と交換で、2つ目は価格です。例えば

1201007,0.006
1201032,0.0119
1201040,0.0106
1201200,0.0052
1201201,0.0345

すべてのファイルに同じ市外局番と交換が含まれているわけではないため、行ごとの比較ではなく、最初のフィールドをキーとして使用する必要があります。次に、file1のfile2との不一致が200、file2より371の低価格、file2より562の高価格というレポートを生成する必要があります。各ファイルを相互に比較するためにこれを生成する必要があるため、この手順はfile3、file4 ....に対して繰り返され、次にfile2がfiles3に対して繰り返されます。以下は私がこれまでに持っているコードで、ディレクトリ内のファイルを取得し、すべてのファイルから合計集計で価格を出力します。

import csv
import os

count = 0
#dir containing CSV files
csvdir="tariff_compare"
dirList=os.listdir(csvdir)
#index all files for later use
for idx, fname in enumerate(dirList):
    print fname
    dic_read = csv.reader(open(fname))
    for row in dic_read:
        key = row[0]
        price = row[1]
        print price
        count += 1
print count
4

3 に答える 3

0

ファイルを比較する前に、おそらくファイルを並べ替えます。次に、mergesort のマージ ステップと同様のアルゴリズムを使用して比較を行います。

重複したレコードをどうするかについてはまだ考える必要があります。たとえば、file1 に 1234567,0.1 が 2 回あり、file2 も 2 回ある場合はどうなるでしょうか。また、file1 に 3 つ、file2 に 5 つ、またはその逆の場合はどうなるでしょうか。

http://en.literateprograms.org/Merge_sort_%28Python%29
http://stromberg.dnsalias.org/~strombrg/sort-comparison/
http://en.wikipedia.org/wiki/Merge_sort
于 2012-06-25T20:55:11.227 に答える
0

これは、すべてのデータがメモリに収まることを前提としています。そうでない場合は、一度にいくつかのファイル セットだけをロードするか、一度に 2 つのファイルだけをロードする必要があります。

比較を行い、出力を summary.csv ファイルに書き込みます (ファイルのペアごとに 1 行)。

import csv
import glob
import os
import itertools

def get_data(fname):
    """
    Load a .csv file
    Returns a dict of {'exchange':float(price)}
    """
    with open(fname, 'rb') as inf:
        items = (row.split() for row in csv.reader(inf))
        return {item[0]:float(item[1]) for item in items}

def do_compare(a_name, a_data, b_name, b_data):
    """
    Compare two data files of {'key': float(value)}

    Returns a list of
      - the name of the first file
      - the name of the second file
      - the number of keys in A which are not in B
      - the number of keys in B which are not in A
      - the number of values in A less than the corresponding value in B
      - the number of values in A equal to the corresponding value in B
      - the number of values in A greater than the corresponding value in B
    """
    a_keys = set(a_data.iterkeys())
    b_keys = set(b_data.iterkeys())

    unique_to_a = len(a_keys - b_keys)
    unique_to_b = len(b_keys - a_keys)

    lt,eq,gt = 0,0,0
    pairs = ((a_data[key], b_data[key]) for key in a_keys & b_keys)
    for ai,bi in pairs:
        if ai < bi:
            lt +=1 
        elif ai == bi:
            eq += 1
        else:
            gt += 1

    return [a_name, b_name, unique_to_a, unique_to_b, lt, eq, gt]

def main():
    os.chdir('d:/tariff_compare')

    # load data from csv files
    data = {}
    for fname in glob.glob("*.csv"):
        data[fname] = get_data(fname)

    # do comparison
    files = data.keys()
    files.sort()
    with open('summary.csv', 'wb') as outf:
        outcsv = csv.writer(outf)
        outcsv.writerow(["File A", "File B", "Unique to A", "Unique to B", "A<B", "A==B", "A>B"])
        for a,b in itertools.combinations(files, 2):
            outcsv.writerow(do_compare(a, data[a], b, data[b]))

if __name__=="__main__":
    main()

編集: user1277476 は良い点です。交換によってファイルを事前に並べ替えた場合 (または既に並べ替えられている場合)、すべてのファイルを同時に反復処理して、メモリ内の各ファイルの現在の行だけを保持することができます。

これにより、各交換エントリについてより詳細な比較を行うことができます - 値を含むファイルの数、または上位または下位の N 値など。

于 2012-06-25T20:27:34.690 に答える
0

ファイルが小さい場合は、次のような基本的なことを行うことができます

data = dict()
for fname in os.listdir(csvDir):
    with open(fname, 'rb') as fin:
        data[fname] = dict((key, value) for key, value in fin.readlines())
# All the data is now loaded into your data dictionary
# data -> {'file1.csv': {1201007: 0.006, 1201032: 0.0119, 1201040: 0.0106}, 'file2.csv': ...}

これで、データ ディクショナリ内のキーとその結果の値を比較するために、すべてに簡単にアクセスできます。

それ以外の場合、メモリにロードできない可能性がある、はるかに大きなデータセットを操作する場合は、一度に 2 つのファイルを操作し、そのうちの 1 つをメモリに保存することを検討することをお勧めします。itertools.combinationsを使用してファイル名の組み合わせのリストを作成すると、combinations(filenames, 2)使用できる一意の組み合わせから2つのファイル名のペアが得られます。

そこからさらに最適化することはできますが、それでうまくいくはずです。

于 2012-06-25T20:31:12.883 に答える