我想从一个目录中读取几个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循环中需要一些帮助?
如果您的所有
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)
编辑:我用谷歌搜索了 https://stackoverflow.com/a/21232849/186078 ..。然而,最近我发现,使用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 ---
darindaCoder‘s 答案的替代方法:
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
如果多个csv文件被压缩,您可以使用zipfile读取全部并拼接,如下所示:
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)
import glob
import os
import pandas as pd
df = pd.concat(map(pd.read_csv, glob.glob(os.path.join('', "my_files*.csv"))))
如果你想递归搜索(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)
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数据帧。
一个liner使用
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
本身不允许您提供额外的参数。
另一个带有列表理解的在线应用程序,它允许在读取时使用参数_csv。
df = pd.concat([pd.read_csv(f'dir/{f}') for f in os.listdir('dir') if f.endswith('.csv')])
基于@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
方法将字典中键的大小减小到仅相关的较小部分。
另一种方法是使用
pathlib
库(通常优先于
os.path
)。
这种方法避免了重复使用pandas。
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)
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)
这就是在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')