关于python:将多个csv文件导入pandas并连接成一个DataFrame

Import multiple csv files into pandas and concatenate into one DataFrame

我想从目录中读取几个csv文件到pandas并将它们连接成一个大的DataFrame。 我虽然无法弄明白。 这是我到目前为止:

1
2
3
4
5
6
7
8
9
10
11
12
13
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循环中需要一些帮助???


如果所有csv文件中都有相同的列,则可以尝试以下代码。
我添加了header=0,以便在读取csv后可以将第一行指定为列名。

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
import glob

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


替代darindaCoder的答案:

1
2
3
4
5
6
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


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


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

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

(来源:http://dask.pydata.org/en/latest/examples/dataframe-csv.html)

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


这里几乎所有的答案都是不必要的复杂(全局模式匹配)或依赖其他第三方库。您可以使用Pandas和python(所有版本)已经内置的所有内容在2行中执行此操作。

对于一些文件 - 1个班轮:

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

对于许多文件:

1
2
3
4
from os import listdir

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

这个设置df的pandas线使用了3个东西:

  • Python的map(函数,iterable)发送给函数(
    pd.read_csv())iterable(我们的列表),它是每个csv元素
    在文件路径中)。
  • Panda的read_csv()函数正常读入每个CSV文件。
  • Panda的concat()将所有这些带到一个df变量下。

  • 编辑:我用谷歌搜索到https://stackoverflow.com/a/21232849/186078。
    然而,最近我发现使用numpy进行任何操作然后将其分配给数据帧而不是在迭代的基础上操纵数据帧本身更快,它似乎也适用于此解决方案。

    我真诚地希望任何人都能在这个页面上考虑这种方法,但是不要将这段巨大的代码作为评论附加在一起并使其不那么易读。

    您可以利用numpy来加速数据帧连接。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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"....]

    时间统计:

    1
    2
    3
    4
    5
    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 ---


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

    1
    2
    3
    4
    5
    6
    7
    8
    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)

    请注意,最后三行可以用一行表示:

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

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

    编辑:多平台递归函数:

    您可以将上述内容包装到多平台功能(Linux,Windows,Mac)中,这样您就可以:

    1
    df = read_df_rec('C:\user\your\path', *.csv)

    这是功能:

    1
    2
    3
    4
    5
    6
    7
    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)

    如果多个csv文件是压缩的,您可以使用zipfile来读取所有文件并连接如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import zipfile
    import numpy as np
    import pandas as pd

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

    train=[]

    for f in range(0,len(ziptrain.namelist())):
        if (f == 0):
            train = pd.read_csv(ziptrain.open(ziptrain.namelist()[f]))
        else:
            my_df = pd.read_csv(ziptrain.open(ziptrain.namelist()[f]))
            train = (pd.DataFrame(np.concatenate((train,my_df),axis=0),
                              columns=list(my_df.columns.values)))

    使用map的一个班轮,但是如果你想指定其他参数,你可以这样做:

    1
    2
    3
    4
    5
    6
    import pandas as pd
    import glob
    import functools

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

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


    我觉得这个方法很优雅。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import pandas as pd
    import os

    big_frame = pd.DataFrame()

    for file in os.listdir():
        if file.endswith('.csv'):
            df = pd.read_csv(file)
            big_frame = big_frame.append(df, ignore_index=True)

    另一个带有列表理解的内联,允许使用read_csv参数。

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


    简单快捷

    导入2个或更多csv,而无需列出名称。

    1
    2
    3
    import glob

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