8

ファイル 1 の最初の行が次の 2 つの .csv ファイルがあります。

MPID,Title,Description,Model,Category ID,Category Description,Subcategory ID,Subcategory Description,Manufacturer ID,Manufacturer Description,URL,Manufacturer (Brand) URL,Image URL,AR Price,Price,Ship Price,Stock,Condition

ファイル 2 の最初の行:

Regular Price,Sale Price,Manufacturer Name,Model Number,Retailer Category,Buy URL,Product Name,Availability,Shipping Cost,Condition,MPID,Image URL,UPC,Description

そして、すべてのファイルの残りの部分が情報で満たされます。

ご覧のとおり、両方のファイルに MPID という共通フィールドがあります (ファイル 1: 列 1、ファイル 2: 列 9、最初の列は列 1)。

この列を見て、これら 2 つのファイルを結合する新しいファイルを作成したいと思います (たとえば、両方のファイルに MPID がある場合、新しいファイルには、この MPID がファイル 1 の両方の行と共に表示されます)。およびファイル 2 からのその行)。1 つの MPID が 1 つのファイルにのみ表示される場合は、この結合されたファイルにも入る必要があります。

ファイルは決してソートされません。

シェルスクリプトまたはpythonのいずれかを使用して、debianマシンでこれを行うにはどうすればよいですか?

ありがとう。

編集: 両方のファイルには、フィールドを区切るもの以外のコンマはありません。

4

6 に答える 6

10

これは、古典的な「リレーショナル結合」の問題です。

いくつかのアルゴリズムがあります。

  • ネストされたループ。1 つのファイルから読み取り、「マスター」レコードを選択します。マスターに一致するすべての「詳細」レコードを見つける他のファイル全体を読み取ります。これは悪い考えです。

  • ソートマージ。共通キーに基づいて、各ファイルを一時コピーに分類します。次に、マスターから読み取り、次にディテールから一致するすべての行を読み取り、マージされたレコードを書き込むことによって、両方のファイルをマージします。

  • 調べる。ファイルの 1 つを、キー フィールドでインデックス付けされたメモリ内のディクショナリに完全に読み込みます。これは、キーごとに複数の子を持つ詳細ファイルでは扱いにくい場合があります。次に、他のファイルを読み取り、辞書で一致するレコードを検索します。

これらのうち、多くの場合、sort-merge が最も高速です。これは完全に unix のsortコマンドを使用して行われます。

ルックアップの実装

import csv
import collections

index = collections.defaultdict(list)

file1= open( "someFile", "rb" )
rdr= csv.DictReader( file1 )
for row in rdr:
    index[row['MPID']].append( row )
file1.close()

file2= open( "anotherFile", "rb" )
rdr= csv.DictReader( file2 )
for row in rdr:
    print row, index[row['MPID']]
file2.close()
于 2009-05-05T20:46:06.167 に答える
2

joinシェルのコマンドを確認する必要があります。また、データをソートする必要があり、おそらく最初の行が失われます。いずれかのデータにコンマが含まれていると、プロセス全体が失敗します。または、フィールドを明確に分割するために使用できる別のフィールドセパレーター (おそらくコントロール A) を導入する CSV に依存するプロセスでデータを処理する必要があります。

別の方法として、Python を使用して、2 つのファイルを 1 組の辞書 (共通の列をキーとする) に読み込み、ループを使用して 2 つの辞書の小さい方のすべての要素をカバーし、もう一方の辞書で一致する値を探します。 . (これは基本的なネストされたループ クエリ処理です。)

于 2009-05-05T20:42:15.023 に答える
0

CSVファイルを操作するためのストリームエディタである私のFOSSプロジェクトCSVfixを見ることができます。他の機能の中でも特に結合をサポートしており、スクリプトを使用する必要はありません。

于 2009-05-05T21:00:33.200 に答える
0

1 つまたは複数の共通の列に基づいて複数のファイル (場合によっては > 2) をマージする場合、Python での最良かつ効率的なアプローチの 1 つは、"brewery" を使用することです。マージのために考慮する必要があるフィールドと、保存する必要があるフィールドを指定することもできます。

import brewery
from brewery
import ds
import sys

sources = [
    {"file": "grants_2008.csv",
     "fields": ["receiver", "amount", "date"]},
    {"file": "grants_2009.csv",
     "fields": ["id", "receiver", "amount", "contract_number", "date"]},
    {"file": "grants_2010.csv",
     "fields": ["receiver", "subject", "requested_amount", "amount", "date"]}
]

すべてのフィールドのリストを作成し、ファイル名を追加して、データ レコードの発信元に関する情報を保存します。ソース定義を調べて、フィールドを収集します。

for source in sources:
    for field in source["fields"]:
        if field not in all_fields:

out = ds.CSVDataTarget("merged.csv")
out.fields = brewery.FieldList(all_fields)
out.initialize()

for source in sources:

    path = source["file"]

# Initialize data source: skip reading of headers
# use XLSDataSource for XLS files
# We ignore the fields in the header, because we have set-up fields
# previously. We need to skip the header row.

    src = ds.CSVDataSource(path,read_header=False,skip_rows=1)

    src.fields = ds.FieldList(source["fields"])

    src.initialize()


    for record in src.records():

   # Add file reference into ouput - to know where the row comes from
    record["file"] = path

        out.append(record)

# Close the source stream

    src.finalize()


cat merged.csv | brewery pipe pretty_printer
于 2015-04-21T23:10:25.170 に答える
0

SQLサーバーを使用して一般的に行われるシェルスクリプトで実行しようとしているようです。そのタスクに SQL を使用することは可能ですか? たとえば、両方のファイルを mysql にインポートして結合を作成し、それを CSV にエクスポートできます。

于 2009-05-05T20:41:46.177 に答える