我想从目录中读取几个CSV文件到熊猫,并将它们连接到一个大的DataFrame。不过我还没弄明白。以下是我目前所掌握的:

import glob
import pandas as pd

# Get data file names
path = r'C:\DRO\DCL_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循环中需要一些帮助?


当前回答

可选择使用pathlib库(通常优先于os.path)。

该方法避免了重复使用pandas concat()/ apping()。

从熊猫文档中可以看到: 值得注意的是,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)

其他回答

darindaCoder的答案的替代方案:

path = r'C:\DRO\DCL_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

使用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本身不允许您提供额外的参数。

我在谷歌上找到了高拉夫·辛格的答案。

然而,到最近为止,我发现使用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 ---

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数据帧。

如果你想递归搜索(Python 3.5或以上),你可以这样做:

from glob import iglob
import pandas as pd

path = r'C:\user\your\path\**\*.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:\user\your\path', *.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)