将多个 CSV 文件导入 pandas 并连接成一个 DataFrame

2024-11-20 08:44:00
admin
原创
53
摘要:问题描述:我想将目录中的几个 CSV 文件读入 pandas 并将它们连接成一个大的 DataFrame。但我还没能弄清楚。以下是我目前所拥有的:import glob import pandas as pd # Get data file names path = r'C:DRODCL_rawdata_f...

问题描述:

我想将目录中的几个 CSV 文件读入 pandas 并将它们连接成一个大的 DataFrame。但我还没能弄清楚。以下是我目前所拥有的:

import glob
import pandas as pd

# Get data file names
path = r'C:DRODCL_rawdata_files'
filenames = glob.glob(path + "/*.csv")

dfs = []
for filename in filenames:
    dfs.append(pd.read_csv(filename))

# Concatenate all data into one DataFrame
big_frame = pd.concat(dfs, ignore_index=True)

我想我需要for循环中的一些帮助?


解决方案 1:

请参阅pandas:IO 工具,了解所有可用.read_方法。

如果所有 CSV 文件都有相同的列,请尝试以下代码。

我已经添加了header=0,以便在读取 CSV 文件的第一行后,可以将其指定为列名。

import pandas as pd
import glob
import os

path = r'C:DRODCL_rawdata_files' # use your path
all_files = glob.glob(os.path.join(path , "/*.csv"))

li = []

for filename in all_files:
    df = pd.read_csv(filename, index_col=None, header=0)
    li.append(df)

frame = pd.concat(li, axis=0, ignore_index=True)

或者,归功于Sid的评论。

all_files = glob.glob(os.path.join(path, "*.csv"))

df = pd.concat((pd.read_csv(f) for f in all_files), ignore_index=True)

  • 通常需要识别每个数据样本,这可以通过向数据框添加新列来实现。

  • pathlib本示例将使用标准库中的 。它将路径视为具有方法的对象,而不是要切片的字符串。

导入和设置

from pathlib import Path
import pandas as pd
import numpy as np

path = r'C:DRODCL_rawdata_files'  # or unix / linux / mac path

# Get the files from the path provided in the OP
files = Path(path).glob('*.csv')  # .rglob to get subdirectories

选项 1:

  • 添加带有文件名的新列

dfs = list()
for f in files:
    data = pd.read_csv(f)
    # .stem is method for pathlib objects to get the filename w/o the extension
    data['file'] = f.stem
    dfs.append(data)

df = pd.concat(dfs, ignore_index=True)

选项 2:

  • 使用以下方法添加具有通用名称的新列enumerate

dfs = list()
for i, f in enumerate(files):
    data = pd.read_csv(f)
    data['file'] = f'File {i}'
    dfs.append(data)

df = pd.concat(dfs, ignore_index=True)

选项 3:

  • 使用列表推导创建数据框,然后用来np.repeat添加新列。

    • [f'S{i}' for i in range(len(dfs))]创建一个字符串列表来命名每个数据框。

    • [len(df) for df in dfs]创建一个长度列表

  • 此选项归功于此绘图答案。

# Read the files into dataframes
dfs = [pd.read_csv(f) for f in files]

# Combine the list of dataframes
df = pd.concat(dfs, ignore_index=True)

# Add a new column
df['Source'] = np.repeat([f'S{i}' for i in range(len(dfs))], [len(df) for df in dfs])

选项 4:

  • 使用一行代码.assign创建新列,并引用C8H10N4O2的评论

df = pd.concat((pd.read_csv(f).assign(filename=f.stem) for f in files), ignore_index=True)

或者

df = pd.concat((pd.read_csv(f).assign(Source=f'S{i}') for i, f in enumerate(files)), ignore_index=True)

解决方案 2:

darindaCoder 答案的替代方案:

path = r'C:DRODCL_rawdata_files'                     # use your path
all_files = glob.glob(os.path.join(path, "*.csv"))     # advisable to use os.path.join as this makes concatenation OS independent

df_from_each_file = (pd.read_csv(f) for f in all_files)
concatenated_df   = pd.concat(df_from_each_file, ignore_index=True)
# doesn't create a list, nor does it append to one

解决方案 3:

import glob
import os
import pandas as pd   
df = pd.concat(map(pd.read_csv, glob.glob(os.path.join('', "my_files*.csv"))))

解决方案 4:

这里几乎所有的答案要么不必要地复杂(全局模式匹配),要么依赖于额外的第三方库。您可以使用 Pandas 和 Python(所有版本)已经内置的所有内容在两行中完成此操作。

对于一些文件 - 单行

df = pd.concat(map(pd.read_csv, ['d1.csv', 'd2.csv','d3.csv']))

对于许多文件

import os

filepaths = [f for f in os.listdir(".") if f.endswith('.csv')]
df = pd.concat(map(pd.read_csv, filepaths))

对于无标题

如果您想要使用 pd.read_csv 更改特定内容(即没有标题),您可以创建一个单独的函数并使用您的地图调用它:

def f(i):
    return pd.read_csv(i, header=None)

df = pd.concat(map(f, filepaths))

设置 df 的这个 pandas 行利用了三件事:

  1. Python 的 map(函数,可迭代)将可迭代对象(我们的列表)发送给函数(
    pd.read_csv()文件路径中的每个 CSV 元素)。

  2. Panda 的read_csv()函数正常读取每个 CSV 文件。

  3. Panda 的concat()将所有这些置于一个 df 变量之下。

解决方案 5:

简便快捷

导入两个或多个 CSV 文件,无需列出姓名。

import glob
import pandas as pd

df = pd.concat(map(pd.read_csv, glob.glob('data/*.csv')))

解决方案 6:

Dask 库可以从多个文件读取数据框:

>>> import dask.dataframe as dd
>>> df = dd.read_csv('data*.csv')

(来源: https: //examples.dask.org/dataframes/01-data-access.html#Read-CSV-files)

Dask 数据框实现了 Pandas 数据框 API 的一个子集。如果所有数据都适合内存,则可以调用df.compute()将数据框转换为 Pandas 数据框。

解决方案 7:

我通过 Google 找到了Gaurav Singh 的回答。

然而,最近我发现使用NumPy进行任何操作然后将其分配给数据框一次比以迭代方式操作数据框本身更快,并且它似乎也适用于这种解决方案。

我确实真诚地希望任何访问此页面的人都能考虑这种方法,但我不想将这一大段代码作为注释附加并降低其可读性。

您可以利用 NumPy 来真正加快数据框的连接速度。

import os
import glob
import pandas as pd
import numpy as np

path = "my_dir_full_path"
allFiles = glob.glob(os.path.join(path,"*.csv"))


np_array_list = []
for file_ in allFiles:
    df = pd.read_csv(file_,index_col=None, header=0)
    np_array_list.append(df.as_matrix())

comb_np_array = np.vstack(np_array_list)
big_frame = pd.DataFrame(comb_np_array)

big_frame.columns = ["col1", "col2"....]

时间统计:

total files :192
avg lines per file :8492
--approach 1 without NumPy -- 8.248656988143921 seconds ---
total records old :1630571
--approach 2 with NumPy -- 2.289292573928833 seconds ---

解决方案 8:

使用一行代码map,但如果您想指定其他参数,您可以执行以下操作:

import pandas as pd
import glob
import functools

df = pd.concat(map(functools.partial(pd.read_csv, sep='|', compression=None),
                    glob.glob("data/*.csv")))

注意:map它本身不允许您提供额外的参数。

解决方案 9:

如果要递归搜索Python 3.5 或更高版本),可以执行以下操作:

from glob import iglob
import pandas as pd

path = r'C:/useryourpath***.csv'

all_rec = iglob(path, recursive=True)     
dataframes = (pd.read_csv(f) for f in all_rec)
big_dataframe = pd.concat(dataframes, ignore_index=True)

请注意,最后三行可以用一行来表达

df = pd.concat((pd.read_csv(f) for f in iglob(path, recursive=True)), ignore_index=True)

** 您可以在此处找到文档。另外,我使用了iglob而不是glob,因为它返回的是迭代器而不是列表。



编辑:多平台递归函数:

您可以将上述内容包装成一个多平台函数(Linux、Windows、Mac),因此您可以执行以下操作:

df = read_df_rec('C:/useryourpath', *.csv)

该函数如下:

from glob import iglob
from os.path import join
import pandas as pd

def read_df_rec(path, fn_regex=r'*.csv'):
    return pd.concat((pd.read_csv(f) for f in iglob(
        join(path, '**', fn_regex), recursive=True)), ignore_index=True)

解决方案 10:

受到MrFun的回答的启发:

import glob
import pandas as pd

list_of_csv_files = glob.glob(directory_path + '/*.csv')
list_of_csv_files.sort()

df = pd.concat(map(pd.read_csv, list_of_csv_files), ignore_index=True)

笔记:

  1. 默认情况下,生成的文件列表glob.glob未排序。另一方面,在许多情况下,需要排序,例如,可能需要分析传感器丢帧数与时间戳。

  2. pd.concat在命令中,如果ignore_index=True没有指定,那么它会保留每个数据框(即列表中的每个单独的 CSV 文件)的原始索引,并且主数据框看起来像

    timestamp    id    valid_frame
0
1
2
.
.
.
0
1
2
.
.
.

使用ignore_index=True,它看起来像:

    timestamp    id    valid_frame
0
1
2
.
.
.
108
109
.
.
.

在我看来,这在人们可能想要手动创建帧丢失数量与一分钟(或任何其他持续时间)箱的直方图并希望基于第一个时间戳进行计算时很有用,例如
begin_timestamp = df['timestamp'][0]

如果没有ignore_index=Truedf['timestamp'][0]则会生成包含所有单个数据帧中第一个时间戳的系列,它不仅仅给出一个值。

解决方案 11:

另一个具有列表理解的单行代码,允许使用read_csv的参数。

df = pd.concat([pd.read_csv(f'dir/{f}') for f in os.listdir('dir') if f.endswith('.csv')])

解决方案 12:

替代使用pathlib库(通常比 更受欢迎os.path)。

此方法避免了迭代使用 pandas concat()/ apped()

来自 pandas 文档:

值得注意的是,concat()(以及 append())会完整复制数据,并且不断重复使用此函数可能会严重影响性能。如果您需要对多个数据集使用该操作,请使用列表推导。

import pandas as pd
from pathlib import Path

dir = Path("../relevant_directory")

df = (pd.read_csv(f) for f in dir.glob("*.csv"))
df = pd.concat(df)

解决方案 13:

如果压缩了多个 CSV 文件,您可以使用zipfile读取所有文件并按如下方式连接:

import zipfile
import pandas as pd

ziptrain = zipfile.ZipFile('yourpath/yourfile.zip')

train = []

train = [ pd.read_csv(ziptrain.open(f)) for f in ziptrain.namelist() ]

df = pd.concat(train)

解决方案 14:

根据Sid的良好回答。

识别缺失或未对齐列的问题

在连接之前,您可以将 CSV 文件加载到中间字典中,该字典可以根据文件名(格式)访问每个数据集dict_of_df['filename.csv']。例如,当列名不一致时,这样的字典可以帮助您识别异构数据格式的问题。

导入模块并定位文件路径:

import os
import glob
import pandas
from collections import OrderedDict
path =r'C:DRODCL_rawdata_files'
filenames = glob.glob(path + "/*.csv")

注意:OrderedDict不是必需的,但它会保持文件的顺序,这可能对分析有用。

将 CSV 文件加载到字典中。然后连接:

dict_of_df = OrderedDict((f, pandas.read_csv(f)) for f in filenames)
pandas.concat(dict_of_df, sort=True)

键是文件名f,值是 CSV 文件的数据框内容。

除了用作f字典键之外,您还可以使用os.path.basename(f)或其他os.path方法将字典中键的大小减少到仅相关的较小部分。

解决方案 15:

import os

os.system("awk '(NR == 1) || (FNR > 1)' file*.csv > merged.csv")

其中NRFNR代表正在处理的行号。

FNR是每个文件中的当前行。

NR == 1包括第一个文件的第一行(标题),同时FNR > 1跳过每个后续文件的第一行。

解决方案 16:

如果出现未命名列问题,请使用此代码沿 x 轴合并多个 CSV 文件。

import glob
import os
import pandas as pd

merged_df = pd.concat([pd.read_csv(csv_file, index_col=0, header=0) for csv_file in glob.glob(
        os.path.join("data/", "*.csv"))], axis=0, ignore_index=True)

merged_df.to_csv("merged.csv")

解决方案 17:

您也可以按照下面的方法进行:

import pandas as pd
import os

new_df = pd.DataFrame()
for r, d, f in os.walk(csv_folder_path):
    for file in f:
        complete_file_path = csv_folder_path+file
        read_file = pd.read_csv(complete_file_path)
        new_df = new_df.append(read_file, ignore_index=True)


new_df.shape

解决方案 18:

考虑使用convtools库,它提供了大量的数据处理原语并在后台生成简单的临时代码。它不应该比 pandas/polars 更快,但有时它可以。

例如,您可以将 csv 文件合并为一个以供进一步重复使用 - 以下是代码:

import glob

from convtools import conversion as c
from convtools.contrib.tables import Table
import pandas as pd


def test_pandas():
    df = pd.concat(
        (
            pd.read_csv(filename, index_col=None, header=0)
            for filename in glob.glob("tmp/*.csv")
        ),
        axis=0,
        ignore_index=True,
    )
    df.to_csv("out.csv", index=False)
# took 20.9 s


def test_convtools():
    table = None
    for filename in glob.glob("tmp/*.csv"):
        table_ = Table.from_csv(filename, header=False)
        if table is None:
            table = table_
        else:
            table = table.chain(table_)

    table.into_csv("out_convtools.csv", include_header=False)
# took 15.8 s

当然如果你只是想获得一个数据框而不写入连接的文件,它将相应地采取4.63 s10.9 spandas在这里更快,因为它不需要 zip 列来将其写回)。

解决方案 19:

import pandas as pd
import glob

path = r'C:DRODCL_rawdata_files' # use your path
file_path_list = glob.glob(path + "/*.csv")

file_iter = iter(file_path_list)

list_df_csv = []
list_df_csv.append(pd.read_csv(next(file_iter)))

for file in file_iter:
    lsit_df_csv.append(pd.read_csv(file, header=0))
df = pd.concat(lsit_df_csv, ignore_index=True)

解决方案 20:

你可以使用Google Drive上的Colaboratory进行以下操作:

import pandas as pd
import glob

path = r'/content/drive/My Drive/data/actual/comments_only' # Use your path
all_files = glob.glob(path + "/*.csv")

li = []

for filename in all_files:
    df = pd.read_csv(filename, index_col=None, header=0)
    li.append(df)

frame = pd.concat(li, axis=0, ignore_index=True,sort=True)
frame.to_csv('/content/drive/onefile.csv')
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   681  
  在项目管理领域,集成产品开发(IPD)流程以其高效、协同的特点,被众多企业视为提升产品竞争力的关键。IPD流程强调跨部门、跨职能的紧密合作,以确保产品从概念到市场各个环节的无缝衔接。然而,实现这一目标并非易事,它需要企业深刻理解并掌握IPD流程中的跨部门协作艺术。本文将深入探讨IPD流程中跨部门协作的三个关键点,旨在为...
IPD项目管理咨询   9  
  掌握IPD流程图:提升团队协作的关键路径在当今快速变化的商业环境中,团队协作的效率与效果直接关系到项目的成功与否。集成产品开发(Integrated Product Development,简称IPD)作为一种先进的研发管理理念,通过跨部门、跨领域的协同工作,能够显著提升产品开发的速度与质量。而IPD流程图,则是这一理...
IPD流程阶段   9  
  IPD流程概述:理解其核心价值与实施背景集成产品开发(Integrated Product Development,简称IPD)是一种先进的产品开发管理理念,它强调跨部门协作、市场导向和快速响应变化的能力。IPD流程不仅关注产品本身的技术创新,更注重将市场、研发、生产、销售等各个环节紧密集成,以实现产品从概念到市场的高...
华为IPD是什么   7  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程以其跨部门协作、高效决策和快速响应市场变化的特点,被众多企业视为提升竞争力的关键。然而,实践IPD流程并非易事,项目管理中的种种错误往往阻碍了其效果的充分发挥。本文旨在深入探讨如何在实施IPD流程时避免这些常见错误,...
IPD框架   7  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用