将多个csv文件导入pandas并连接到一个DataFrame中

时间:2014-01-03 15:00:47

标签: python pandas csv dataframe concatenation

我想将目录中的几个csv文件读入pandas并将它们连接成一个大的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循环中需要一些帮助???

19 个答案:

答案 0 :(得分:295)

如果您的所有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)

答案 1 :(得分:220)

darindaCoder's answer的替代方案:

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

答案 2 :(得分:40)

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

答案 3 :(得分:13)

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

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

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

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

答案 4 :(得分:12)

编辑:我用Google搜索https://stackoverflow.com/a/21232849/186078。 然而,最近我发现使用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 ---

答案 5 :(得分:10)

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

对于一些文件-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种东西:

  1. Python's map (function, iterable)发送到函数( pd.read_csv())是每个csv元素的可迭代(我们的列表) 在文件路径中。)
  2. 熊猫的read_csv()函数正常读取每个CSV文件。
  3. Panda的concat()将所有这些都放在一个df变量下。

答案 6 :(得分:9)

如果您想递归搜索 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)

您可以找到** here的文档。另外,我使用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)

答案 7 :(得分:4)

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

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

答案 8 :(得分:2)

我发现这种方法非常优雅。

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)

答案 9 :(得分:2)

import os

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

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

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

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

答案 10 :(得分:2)

基于@Sid的正确答案。

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

导入模块并找到文件路径:

import os
import glob
import pandas
from collections import OrderedDict
path =r'C:\DRO\DCL_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方法将字典中键的大小减小到相关的较小部分。< / p>

答案 11 :(得分:1)

如果有人遇到未命名列问题,可以使用此代码沿 x 轴合并多个 csv 文件。

from PIL import Image
import fitz
import os


def start():
    doc = fitz.open("cs2103g0052_019_549291_ca_cs_sb_sb_fy22q2wk7_oa_showcase-premium-fr_XXXxXXX_jsos.pdf")
    try:
        os.mkdir("Extract Images")
    except:
        pass
    DIR = "Extract Images"
    for i in range(len(doc)):
        for img in doc.getPageImageList(i):
            xref = img[0]
            pix = fitz.Pixmap(doc, xref)
            if pix.n < 5:  # this is GRAY or RGB
                # file_path = os.path.join(DIR, "screenshot%d.png" % (count + 1))
                pix.writePNG(os.path.join(DIR, "p%s-%s.png" % (i, xref)))
            else:  # CMYK: convert to RGB first
                pix1 = fitz.Pixmap(fitz.csRGB, pix)
                pix1.writePNG(os.path.join(DIR, "p%s-%s.png" % (i, xref)))
                pix1 = None
            pix = None

start()

答案 12 :(得分:1)

使用map的一个内衬,但是如果您要指定其他参数,则可以执行以下操作:

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本身不能让您提供其他参数。

答案 13 :(得分:0)

方便快捷

导入2个或更多csv,而不必列出名称。

import glob

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

答案 14 :(得分:0)

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

此方法避免了熊猫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)

答案 15 :(得分:0)

您也可以通过这种方式做到这一点:

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

答案 16 :(得分:0)

另一种带有列表理解功能的在线控件,允许将参数与read_csv一起使用。

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

答案 17 :(得分:-1)

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)

答案 18 :(得分:-2)

这是在Google云端硬盘上使用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')