如何使用 pandas 从文件夹中读取和组合具有相似名称的 .csv 文件

Posted

技术标签:

【中文标题】如何使用 pandas 从文件夹中读取和组合具有相似名称的 .csv 文件【英文标题】:How to read and combine .csv files with similar names from a folder using pandas 【发布时间】:2021-10-09 19:49:38 【问题描述】:

我在文件夹C/Downloads 中有如下文件名-

Mango001-003.csv
Mango004-006.csv
Mango007-100.csv
Applefruit.csv
Banana001-003.csv
Banana004-006.csv

如何分别导入水果文件,然后将相同的水果文件合并成一个文件?

预期的输出是 Mango 的一个输出,Apple 的一个输出和 Banana 的一个输出

import os
import re
data_files = os.listdir(r'C:\Downloads')
def load_files(filenames):
    # Pre-compile regex for code readability
    regex = re.compile(r'Mango.*?.csv')
    
    # Map filenames to match objects, filter out not matching names
    matches = [m for m in map(regex.match, filenames) if m is not None]
    
    li = []
    for match in matches:
                
        df = pd.read_csv(match, index_col=None, header=0, dtype=object)
        li.append(df)
        
    #Concatenating the data
    frame = pd.concat(li, axis=0, ignore_index=True)
    return (frame)
    
df  = load_files(data_files)
print(df.shape)
df.head(2)

我遇到了错误。另外,不可能这么复杂,一定是我做错了什么。

【问题讨论】:

【参考方案1】:

我认为最简单的方法是使用glob.glob 获取以特定水果名称(这里我使用芒果)开头的所有文件的列表,然后使用pd.concat 将它们连接在一起。

data_files = r"path\to\folder\containing\csv"
df_mango= pd.DataFrame()
df_mango= pd.concat(map(pd.read_csv,glob.glob(os.path.join(data_files,'mango*.csv'))), ignore_index= True)
df_mango.to_csv('mango.csv')

这是我试过的例子:

mango0110.csv
   A  B  C
0  1  2  3
mango01220.csv
   A  B  C
0  4  5  6
To get:
   A  B  C
0  1  2  3
1  4  5  6

【讨论】:

它完成了这项工作,但我无法插入分隔符 df = pd.read_csv(filename, sep=",") 为什么需要分隔符?我假设所有文件名都以水果的名称开头,并且 glob.glob(os.path.join(data_files,'mango*.csv') 获取以 mango 开头的文件,然后将它们全部连接起来 显然 * 说明了芒果后面的任何内容。如我的示例所示,如 mango0110.csv 等 假设我的文件中的值用“~!”分隔我想导入数据集 哇,这很有趣。到目前为止,我真的考虑过除逗号分隔值之外的任何东西(因为我在你的示例中只找到了 csv)。让我试试这种情况:)【参考方案2】:

也许不是最好的方法,但是对于给定的文件名......

试试:

import pandas as pd
import glob
import re

path = r'./files' # use your path
all_files = glob.glob(path + "/*.csv")

fruits = []

# for all files in the folder get the fruit name
# this could be where things go wrong if the regex does not
# account for all filename types.  Pattern may need tweaking
# example https://regex101.com/r/E69LWa/1
for file in all_files:
    cleanFile = file.replace('fruit', '')
    match = re.match(r'^.*/([A-Za-z]+)',cleanFile)
    fruits.append(match.group(1))

# There will be one output for Mango, one for Apple & one for Banana hence three...
dfs_man = []
dfs_ban = []
dfs_app = []

# for all files create a df and append to the correct list holding other dfs of the same fruit
for i, file in enumerate(all_files):
    df = pd.read_csv(file)
    if fruits[i] == 'Mango':
        dfs_man.append(df)
    elif fruits[i] == 'Banana':
        dfs_ban.append(df)
    elif fruits[i] == 'Apple':
        dfs_app.append(df)

# concatenate if more than one df in list, else just get the df out of list
if len(dfs_man) > 1:
    df_mango = pd.concat(dfs_man, ignore_index=True)
elif len(dfs_man) == 1:
    df_mango = dfs_man[0]
if len(dfs_ban) > 1:
    df_banana = pd.concat(dfs_ban, ignore_index=True)
elif len(dfs_ban) == 1:
    df_banana = dfs_ban[0]
if len(dfs_app) > 1:
    df_apple = pd.concat(dfs_app, ignore_index=True)
elif len(dfs_app) == 1:
    df_apple = dfs_app[0]
    
print(df_mango.shape, df_banana.shape, df_apple.shape)

【讨论】:

@VidyaGanesh 什么不安全?【参考方案3】:

谢谢@Vidya Ganesh

data_files = r'C:\Downloads'
list_file_names = ['Mango','Apple','Banana']
for i in list_file_names:
    name = i
    df = pd.DataFrame()
    df= pd.concat(map(pd.read_csv,glob.glob(os.path.join(data_files,str(name)+'*.csv'))), ignore_index= True)
    df = df.loc[:1000,:]
    print (name)
    print (df.shape)
    df.to_csv(str(name)+".csv")

【讨论】:

以上是关于如何使用 pandas 从文件夹中读取和组合具有相似名称的 .csv 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 pandas read_pickle 从 qrc 资源文件中读取包含 pandas 数据框的 pickle 文件?

如何从一个文件中读取多个 JSON 数据列表到 Pandas

如何使用 pandas 从 GitHub 读取 CSV 文件

从压缩文件夹中的文件夹中读取 txt 文件作为 pandas 数据框

python:pandas - 如何将前两行 pandas 数据帧组合到数据帧头?

如何通过对第 3 列中的值求和,将前 2 列中具有相同值的 Pandas Dataframe 行组合在一起?