从多个 csv 文件中获取一个特定列并合并为一个

Posted

技术标签:

【中文标题】从多个 csv 文件中获取一个特定列并合并为一个【英文标题】:Grab one specific column from multiple csv files and merge into one 【发布时间】:2016-09-17 21:04:36 【问题描述】:

我只想从我的所有 csv 文件中获取第 4 列中的数据并将数据写入单个文件。每个第 4 列都有一个唯一的标题名称,其中包含根文件夹的名称+csv 名称,例如FolderA1

文件夹A /

1.csv |INFO  INFO  INFO  FolderA1  INFO
       Apple Apple Apple Orange    Apple

2.csv |INFO  INFO  INFO  FolderA2 INFO
       Apple Apple Apple Cracker  Apple

3.csv |INFO  INFO  INFO  FOLDERA3 INFO
       Apple Apple Apple Orange  Apple

如何仅将第 4 列数据过滤到单个 .xlsx 文件中,并将下一个文件夹 csv 放入新工作表中或将其与以前的文件夹 csv 分开?

concentrated.xlsx | FOLDERA1 FOLDERA2 FOLDERA3   FOLDERB1 FOLDERB2 FOLDERB3
                    ORANGE   CRACKER   ORANGE    ORANGE   CRACKER  ORANGE

【问题讨论】:

脚本是否需要遍历多个文件夹?您只提到了 FolderA。 是的,抱歉,我不是很清楚。它需要像 FolderA 1,2,3.csv FolderB 1,2,3.csv 一样,并且能够将其放入单个文件中。我制作的 for 循环只能在单个文件夹中执行 csv 每个文件夹是否只有 3 个 csv 文件?您似乎只提到每个文件夹 3 个。 【参考方案1】:

我会使用pandas.read_csv附带的usecols参数。

def read_4th(fn):
    return pd.read_csv(fn, delim_whitespace=1, usecols=[3])

files = ['./1.csv', './2.csv', './3.csv']

big_df = pd.concat([read_4th(fn) for fn in files], axis=1)

big_df.to_excel('./mybigdf.xlsx')

对于多个文件夹,请使用glob

假设您有 2 个文件夹 'FolderA' 和 'FolderB' 都位于文件夹 './' 中,并且您想要两个文件夹中的所有 csv 文件。

from glob import glob

files = glob('./*/*.csv')

然后按照上面的说明运行其余部分。

【讨论】:

谢谢,您的代码适用于一个文件夹。但是我怎样才能让它遍历其他文件夹并将其添加到同一个 xlsx 中呢?也许为每个文件创建一个新工作表或追加? 您需要一种将文件名放入列表的方法。您可以使用glob 库来执行此操作。我将在答案中举一个例子。 非常好的解决方案,我尝试了类似的方法,但忘记了分隔符,我找不到问题。 ;)【参考方案2】:

其他答案建议使用Pandas 作为选项,这肯定会奏效,但如果您正在寻找纯粹使用 Python 库的解决方案,您可以尝试使用 CSV 模块和迭代器。

这里需要注意的是,根据您需要连接的文件数量,您可能会遇到内存限制。但撇开这些不谈,这里有一种方法。

基本 Python 库

import csv
from glob import glob
from itertools import izip_longest, imap

# Use glob to recursively get all CSV files. Adjust the pattern according to your need
input_files = (open(file_path, 'rb') for file_path in glob('*.csv'))

# Using generators, we can wrap all the CSV files in reader instances
input_readers = (csv.reader(input_file) for input_file in input_files)

with open('output.csv', 'wb') as output_file:
    output_writer = csv.writer(output_file)

    # izip_longest will return a tuple of the next value 
    # for all the iterables passed as parameters
    # In this case, this means the next row for all the input_readers
    for rows in izip_longest(*input_readers):

        # We extract the fourth column in all the rows
        # Note that this presumes that all files have a fourth column.
        # Some error checking/handling might be required if 
        # you are not sure that's the case 
        fourth_columns = imap(lambda row: row[3], rows)

        # Write to the output the row that is all the 
        # fourth columns for all the readers
        output_writer.writerow(fourth_columns)

# Clean up the opened files
map(lambda f: f.close(), input_files)

通过使用生成器,您可以最大限度地减少一次加载到内存中的数据量,同时保持一种非常 Pythonic 的方法来解决问题。

使用glob 模块可以更轻松地加载具有已知模式的多个文件,这似乎是您的情况。如果更合适,请随意将其替换为其他形式的文件查找,例如 os.path.walk。

【讨论】:

【参考方案3】:

这样的事情应该可以工作:

import pandas as pd

input_file_paths = ['1.csv', '2.csv', '3.csv']

dfs = (pd.read_csv(fname) for fname in input_file_paths)

master_df = pd.concat(
    (df[[c for c in df.columns if c.lower().startswith('folder')]]
        for df in dfs), axis=1)

master_df.to_excel('smth.xlsx')

df[[c for c in df.columns if c.lower().startswith('folder')]] 行是由于您的示例文件夹列的格式不一致。

【讨论】:

以上是关于从多个 csv 文件中获取一个特定列并合并为一个的主要内容,如果未能解决你的问题,请参考以下文章

怎么用命令行把多个csv文件合并成一个xls或者xlsx文件

如何将多个 csv 文件合并为一个 csv 文件

使用 PowerShell 将多个 CSV 文件合并为一个

如何将多个csv按行合并?(不是首尾相接的按列合并)

根据特定列合并多个 CSV 文件 - Python

如何批处理将多个文件夹下的excel文件(xls,xlsx,csv等)合并成一个文件?