从多个 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 文件中获取一个特定列并合并为一个的主要内容,如果未能解决你的问题,请参考以下文章