在行数不等的情况下,如何按公共列合并两个csv文件?

2024-10-01 15:47:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一套100份档案。包含美国各州人口普查信息的50份文件。另外50个是需要与每个州的正确文件合并的地理数据。在

对于每个州,普查文件及其对应的地理文件由一个公共变量LOGRECNO关联,即普查文件中的第10列和geo文件中的第7列。在

问题是geo文件比census文件有更多的行;我的人口普查数据不包括地理位置的某些子集,因此比geo数据文件的行数更少。在

如何将人口普查数据与地理日期合并(只保留存在普查数据的行/地理位置,而不关心其余的行/地理位置)?在

我是Python的新手,我知道如何在Python中进行基本的csv文件I/o。同时操纵两个CSV被证明是令人困惑的。在

示例:

样品状态_人口普查.csv在

Varname 1 Varname 2 ... Varname 10 (LOGRECNO) ... Varname 16000
xxx       xxx    ...       1             ...               xxx
xxx       xxx    ...       2             ...               xxx
...
...
xxx       xxx   ...        514           ...                xxx
xxx       xxx   ...        1312          ...                xxx
...
...
xxx       xxx   ...        1500          ...                xxx

样品状态_地理.csv在

^{pr2}$

预期输出(不要合并sample\u状态中不存在的LOGRECNO值的行_人口普查.csv)在

Varname 1 Varname 2 ... Varname 10 (LOGRECNO) GeoVarname 1 GeoVarname 2 ... GeoVarname 65 Varname 11... Varname 16000 
xxx       xxx    ...       1  yyy yyy ... yyy xxx            ...               xxx
xxx       xxx    ...       2 yyy yyy ... yyy xxx            ...               xxx
...
...
xxx       xxx   ...        514    yyy yyy ... yyy xxx       ...                xxx
xxx       xxx   ...        1312      yyy yyy ... yyy xxx    ...                xxx
...
...
xxx       xxx   ...        1500    yyy yyy ... yyy xxx      ...                xxx

Tags: 文件csv数据状态样品地理位置档案地理
2条回答

将较短文件中的数据读入内存,并放入LOGRECNO行上键控的字典中:

import csv

with open('sample_state_census.csv', 'rb') as census_file:
    reader = csv.reader(census_file, delimiter='\t')
    census_header = next(reader, None)  # store header
    census = {row[9]: row for row in reader}

然后使用此字典匹配地理数据,写出匹配项:

^{pr2}$

这一切都是假设人口普查文件不会太大,以至于占用太多内存。如果是这样的话,你将不得不使用一个数据库代替(将所有数据读入一个SQLite数据库,以相同的方式匹配地理数据)。在

对于基于一个或多个公共列合并多个文件(甚至是2个),python中最有效的方法之一就是使用“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"]}
]

创建所有字段的列表并添加文件名以存储信息

关于数据记录的来源

^{pr2}$

浏览源代码定义并收集字段

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

相关问题 更多 >

    热门问题