2009-05-05 3 views
8

그래서 나는이 개 .CSV 파일이 나머지 모든 파일은 정보로 채워져 있습니다.일반적인 열을 기준으로 2 개 .CSV 파일을 결합

두 파일 모두 MPID (파일 1 : 열 1, 파일 2 : 열 9, 첫 번째 열은 열 1)라는 공통 필드가 있습니다.

이 열을보고이 두 파일을 결합하는 새 파일을 만들고 싶습니다 (두 파일에 MPID가 있으면 새 파일에이 MPID가 파일 1의 행과 파일 2의 행). 하나의 MPID가 하나의 파일에만 나타나면이 결합 된 파일에도 들어 있어야합니다.

파일은 어떤 방식으로도 정렬되지 않습니다.

쉘 스크립트 나 파이썬이있는 데비안 시스템에서는 어떻게해야합니까?

감사합니다.

EDIT : 두 파일 모두 필드를 구분하는 것 이외의 쉼표가 없습니다.

답변

0

일반적으로 SQL 서버를 사용하여 수행되는 쉘 스크립트에서 수행하려고하는 것처럼 보입니다. 해당 작업에 SQL을 사용할 수 있습니까? 예를 들어 두 파일을 모두 mysql로 ​​가져온 다음 조인을 만든 다음 CSV로 내 보냅니다.

1

셸에서 join 명령을 확인해야합니다. 또한 데이터를 정렬해야하며 첫 번째 줄을 잃어 버릴 수도 있습니다. 데이터 중 하나에 쉼표가 포함되어 있으면 전체 프로세스가 무너집니다. 또는 필드를 명확하게 구분하는 데 사용할 수있는 다른 필드 구분자 (아마도 control-A)를 도입 한 CSV에 민감한 프로세스로 데이터를 처리해야합니다.

파이썬을 사용하는 대안은 두 파일을 한 쌍의 사전 (공통 열에 맞추어 짐)에 읽어 들인 다음 루프를 사용하여 두 사전 중 작은 것에있는 모든 요소를 ​​포함하여 일치를 찾습니다. 다른 값. (기본 중첩 루프 쿼리 처리입니다.)

+1

큰 일을 조인; 입력 파일은 키에서 정렬되어야합니다. 또한 임의의 csv 파일을 읽을 수 없습니다. 특히 인용 된 필드 내의 쉼표는 해당 레코드에 대한 모든 필드 넘버를 이동시킬 것입니다. – Javier

+0

@Javier : 동의 했으므로 - 내 의견을 보지 않고도 내 대답을 업데이트 한 이유는 무엇입니까? 편집). –

13
sort -t , -k index1 file1 > sorted1 
sort -t , -k index2 file2 > sorted2 
join -t , -1 index1 -2 index2 -a 1 -a 2 sorted1 sorted2 
+6

인용 부호가있는 쉼표를주의하십시오! 어떤 종류의 인용이나 인용문을 따르지 않는다. – Javier

9

이것은 고전적인 "관계형 조인"문제입니다.

몇 가지 알고리즘이 있습니다.

  • 중첩 루프. 하나의 파일에서 "마스터"레코드를 읽습니다. 마스터와 일치하는 모든 "세부 사항"레코드를 찾는 전체 파일을 읽습니다. 이것은 나쁜 생각입니다.

  • 정렬 - 병합. 각 파일을 공통 키에 따라 임시 사본으로 정렬합니다. 그런 다음 마스터에서 읽은 다음 세부 사항에서 일치하는 모든 행을 읽고 병합 된 레코드를 작성하여 두 파일을 병합합니다.

  • 조회. 파일 중 하나를 메모리에서 키 필드로 색인 된 사전으로 완전히 읽습니다. 세부 사항 파일에는 까다로울 수 있습니다. 세부 파일에서는 키당 여러 개의 하위 항목이 있습니다. 그런 다음 다른 파일을 읽고 사전에서 일치하는 레코드를 조회합니다.

이 중 정렬 병합이 가장 빠른 경우가 많습니다. 이것은 유닉스 sort 명령을 사용하여 완전히 수행됩니다.

당신은 CSV 파일을 조작하기위한 스트림 편집기 내 FOSS 프로젝트 CSVfix, 한 번 봐 걸릴 수

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() 
+0

파이썬 2.2 이후로, DictReader는 __getitem__을 구현하지 않았다. 이것은 속도상의 이유로 수행되었습니다. 따라서 코드 : index[rdr['MPID']].append(row) 은 AttributeError와 함께 실패합니다. DictReader 인스턴스에는 '__getitem__'속성이 없습니다. – uman

+0

@uman : DictReader의 결과는 1 급 'dict' 개체입니다. 'dict' 메소드는 그대로 유지합니다. –

+0

@ S.Lott : 코드가 잘못되었을 수 있습니다. 저는 Python으로 매우 녹슬었지만 MPID의 예제를 사용하면 AttributeError가 발생합니다. 참조 : http://pastebin.com/VJgSfA3u P. 누구든지 서식에 형식을 포함시키는 방법을 알고 있습니까? – uman

0

조회 구현입니다. 다른 기능 중 조인을 지원하며 스크립팅이 필요하지 않습니다.

0

하나 이상의 공통 열을 기반으로 여러 파일 (심지어> 2)을 병합하려면 파이썬에서 가장 효율적이고 효율적인 방법 중 하나는 "양조장"을 사용하는 것입니다. 병합을 위해 고려해야 할 필드와 저장해야 할 필드를 지정할 수도 있습니다.

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"]} 
] 

모든 필드의 목록을 작성하고 소스 정의를 통해 데이터의 출처에 대한 정보를 저장하는 파일 이름을 records.Go 추가하고 필드 수집 :

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