Python 将多个csv文件导入熊猫并连接到一个数据帧中
我想把一个目录中的几个csv文件读入pandas,并将它们连接到一个大数据帧中。不过我还没弄明白。以下是我到目前为止的情况: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
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元素
在文件路径中)一个使用
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
)
此方法避免了重复使用pandasconcat()
/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")