Python 将多个csv文件导入熊猫并连接到一个数据帧中

Python 将多个csv文件导入熊猫并连接到一个数据帧中,python,pandas,csv,dataframe,concatenation,Python,Pandas,Csv,Dataframe,Concatenation,我想把一个目录中的几个csv文件读入pandas,并将它们连接到一个大数据帧中。不过我还没弄明白。以下是我到目前为止的情况: 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文件读入pandas,并将它们连接到一个大数据帧中。不过我还没弄明白。以下是我到目前为止的情况:

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
后,可以将第一行指定为列名

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)

编辑:我用谷歌搜索了一下。 但是最近我发现,使用numpy进行任何操作,然后将其分配给dataframe一次,要比在迭代的基础上操作dataframe本身更快,而且在这个解决方案中似乎也能工作

我真的希望任何人点击这个页面来考虑这个方法,但是不想把这个巨大的代码附加在一个注释上,使它变得不可读。 您可以利用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 ---
替代方案:


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

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)

    

如果要递归搜索(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)

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

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


Dask数据帧实现了熊猫数据帧API的一个子集。如果所有数据都放入内存,则可以将数据帧转换为数据帧。

这里几乎所有的答案都不必要地复杂(全局模式匹配),或者依赖其他第三方库。使用Pandas和python(所有版本)已经内置的所有东西,您可以在两行代码中完成这项工作

对于一些文件-1行程序:

df = pd.concat(map(pd.read_csv, ['data/d1.csv', 'data/d2.csv','data/d3.csv']))
对于许多文件:

from os import listdir

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

设置df的这条线利用了3个方面:

  • 发送到函数(
    pd.read\u csv()
    )iterable(我们的列表),它是每个csv元素 在文件路径中)
  • Panda的函数正常读取每个CSV文件
  • Panda's将所有这些放在一个df变量下

  • 一个使用
    map
    的行程序,但如果要指定其他参数,可以执行以下操作:

    将熊猫作为pd导入
    导入glob
    导入功能工具
    df=pd.concat(map(functools.partial(pd.read_csv,sep='|',compression=None),
    glob.glob(“data/*.csv”))
    

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

    另一个具有列表理解功能的联机参数,允许使用带read\u csv的参数

    df = pd.concat([pd.read_csv(f'dir/{f}') for f in os.listdir('dir') if f.endswith('.csv')])
    
    轻快 导入两个或多个
    csv
    ,而无需列出姓名

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

    基于@Sid的好答案

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

    导入模块并定位文件路径: 注意:
    OrderedDict
    不是必需的, 但它将保持文件的顺序,这可能对分析有用

    将csv文件加载到字典中。然后连接: 键是文件名
    f
    ,值是csv文件的数据帧内容。
    除了使用
    f
    作为字典键外,您还可以使用
    os.path.basename(f)
    或其他方法将字典中键的大小减小到只有较小的相关部分。

    使用
    pathlib
    库(通常优于
    os.path

    此方法避免了重复使用pandas
    concat()
    /
    apped()

    从熊猫文档:
    值得注意的是,concat()(因此append())生成了数据的完整副本,不断重用此函数会对性能造成重大影响。如果需要对多个数据集使用该操作,请使用列表


    这就是在Google Drive上使用Colab的方法

    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')
    

    您也可以这样做:

    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
    
    其中,
    NR
    FNR
    表示正在处理的行数

    FNR
    是每个文件中的当前行


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

    您的代码不做任何操作,因为您没有附加到
    dfs
    列表中,是否要将该行
    data=pd.read\u csv(filename)
    替换为
    dfs.append(pd.read_csv(filename)
    。然后您需要循环查看列表和
    concat
    ,我认为
    concat
    不会对
    df
    的列表起作用。此外,您在最后一行中混合了模块别名和模块名称,它不应该是
    big\u frame=pd.concat(dfs,ignore\u index=True)
    ?,无论如何,一旦你有了一个数据帧列表,你就需要在列表上迭代,并将其压缩到
    big\u frame
    是的,我编辑了代码,但是我仍然无法从csv文件中构建一个连接的数据帧,我对python是新手,所以我需要更多的帮助。你现在需要循环
    dfs
    ,所以类似于dfs中的df:big\u frame.concat(df,ignore\u index=True)应该可以工作,您也可以尝试
    附加
    而不是
    import os
    import glob
    import pandas
    from collections import OrderedDict
    path =r'C:\DRO\DCL_rawdata_files'
    filenames = glob.glob(path + "/*.csv")
    
    dict_of_df = OrderedDict((f, pandas.read_csv(f)) for f in filenames)
    pandas.concat(dict_of_df, sort=True)
    
    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)
    
    import pandas as pd
    import glob
    
    path = r'C:\DRO\DCL_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)
    
    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')
    
    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
    
    import os
    
    os.system("awk '(NR == 1) || (FNR > 1)' file*.csv > merged.csv")