【问题标题】:Concatenating Multiple Large .CSV Files with Varying Structures连接多个具有不同结构的大型 .CSV 文件
【发布时间】:2022-01-06 17:57:20
【问题描述】:

我有大约 40 个 .csv 文件(范围从大约 100mb 到 600mb),我想将它们连接成一个 .csv 文件。我使用的数据是使用来自 FNMA 的预构建 R 代码构建的,该代码将较大的原始数据文件聚合成更易于管理的格式。但是,当尝试连接数据文件时,我收到以下错误,表明文件之间的字段计数不匹配:“ParserError: Error tokenizing data.C error: Expected 75 fields in line 10, saw 76”。由于文件之间的大多数字段是同质的,我试图从本质上垂直地对数据进行内部连接以解决此问题,但我还没有找到合理的解决方案。我认为只修剪 .R 代码来编写我知道存在的字段可能是有意义的,但我更喜欢使用 Python 的解决方案,因为这些数据需要大量时间来处理并且预构建的代码相当庞大。 我将在下面包含我一直尝试使用的 Python 代码(如果需要,我很乐意分享 .R 代码,但它有 600 多行):

import os
import glob
import pandas as pd
#set working directory
os.chdir("folder directory")

#find all csv files in the folder
#use glob pattern matching -> extension = 'csv'
#save result in list -> all_filenames
extension = 'csv'
all_filenames = [i for i in glob.glob('*.{}'.format(extension))]
#print(all_filenames)

#combine all files in the list
combined_csv = pd.concat([pd.read_csv(f) for f in all_filenames ], ignore_index=True, sort=False)
#export to csv
combined_csv.to_csv( "FNMA Data Aggregated.csv", index=False, encoding='utf-8-sig')
combined_csv

【问题讨论】:

  • 您能分享一些 .csv 文件的结构吗?
  • @cjdeschene,您使用的是什么操作系统?如果您使用的是基于 *NIX 的操作系统,则可以使用cat 或其他命令行工具。
  • @Adirius 每个文件有大约 400,000 多条记录(行)和 74-76 个字段(其中大部分是同质的)。有数字、字符串和日期类型的混合。如果您特别需要其他结构元素,请告诉我,我很乐意分享。
  • @iembry 我正在使用 Windows 10 并通过 pip 运行 Python

标签: python r csv concatenation


【解决方案1】:

如果我了解您的设置...

假设您有以下两个文件,file1.csv

c1,c2
1,a
2,b
3,c

file2.csv

c1,c3
4,iv
5,v
6,vi

您是否希望 stacked.csv 如下所示?

c1,c2,c3
1,a,
2,b,
3,c,
4,,iv
5,,v
6,,vi

如果是这样,您需要将其分解为三个步骤:

  1. 读取所有 CSV 的列,并将这些列聚合为所有单个标题的超集
  2. 创建 stacked.csv 并写入超集标头
  3. 读取每个 CSV 并将其值写入 stacked.csv 中超集标题下的相应列名中
import csv

file_names = [
    'file1.csv',
    'file2.csv',
]


def print_debug(e, row, fname, super_list):
    if not 'dict contains fields' in str(e):
        raise

    print(f'''While trying to write row for file {fname}:
{row}

received error: "{e}"

Superset of headers is:
{super_list}
''')


# Aggregate headers
super_set = set()
for fname in  file_names:
    with open(fname, newline='') as f:
        reader = csv.DictReader(f)
        super_set.update(set(reader.fieldnames))

# DictReader needs this to be a list, not a set
super_set.add('file')
super_list = list(super_set)

with open('stacked.csv', 'w' , newline='') as f_out:
    writer = csv.DictWriter(f_out, fieldnames=super_list)
    writer.writeheader()

    for fname in  file_names:
        with open(fname, newline='') as f_in:
            reader = csv.DictReader(f_in)
            for row in reader:
                row['file'] = fname
                try:
                    writer.writerow(row)
                except ValueError as e:
                    print_debug(e, row, fname, super_list)
                except:
                    raise

当我对我的两个示例输入运行它时,我得到:

c1 c2 c3 file
1 a file1.csv
2 b file1.csv
3 c file1.csv
4 iv file2.csv
5 v file2.csv
6 vi file2.csv

【讨论】:

  • 感谢您的反馈。我在上面实现了您的代码并收到以下错误:“ValueError:dict contains fields not in fieldnames:None”。知道是什么原因造成的吗?
  • 您的 CSV 文件有标题吗?如果他们不这样做,这将不起作用。
  • 是的,它们都有标题(我假设您指的是字段名称)。
  • 该错误可能来自最后一行writer.writerow(row),这意味着row 中有一个字段在super_set/super_list 中不存在。如果您在第 1 步中迭代与第 3 步相同的文件列表,我看不出这怎么可能。我添加了一些异常处理和打印调试来尝试帮助您找到文件和标题,这不是在super_set 中收集的。
  • 顺便说一句,为了您自己的测试,修改您的文件列表以尝试仅堆叠前两个文件并确保至少可以正常工作。
猜你喜欢
  • 2021-09-07
  • 2021-01-23
  • 2020-09-09
  • 2017-12-01
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多