文件夹有五个或六个.csv文件。我想使用pd.read_csv()一次读取所有这些文件,然后将每个df保存为jupyter中的变量,该变量特定于文件名,而没有任何路径或文件类型。
例如,说这是两个文件:
'../main/data/csv_files/file_1.csv'
'../main/data/csv_files/file_2.csv'
我可以对每个人执行此操作
file_1 = pd.read_csv('../main/data/csv_files/file_1.csv')
file_2 = pd.read_csv('../main/data/csv_files/file_2.csv')
但是,我的问题是,如何在保持文件名命名约定的情况下,对循环或对所有文件立即执行所有操作?
我可以使用glob或其他方式来获取csv文件的所有文件路径的列表。然后,我可以创建一个字典将它们全部放入,但是它将使用它们的完整文件路径作为名称。
path = r'../main/data/csv_files'
files = glob.glob(path + '/*.csv')
dfs = {}
for x in files:
dfs[x] = pd.read_csv(x)
这可行,但完整路径的命名并不理想。
答案 0 :(得分:0)
如果您的文件名不是来自网络等不受信任的来源,请使用exec
运行python命令。
import ntpath
for x in files:
# /a/b/c.csv => c.csv
file_without_path = ntpath.basename(x)
# c.csv => c
file_without_extension = file_without_path[:-4]
# execute "c = pd.readcsv('a/b/c.csv')"
exec("{} = pd.read_csv('{}')".format(file_without_extension, x))
如果不能信任文件名,则不要执行此操作,因为将执行文件名中的任何代码。
答案 1 :(得分:0)
您要尝试做的事情-创建与文件同名的动态局部变量是一种我很少遇到的模式,并且可能会出现问题,但是我已经展示了一种方法下面也是如此。相反,您应该尝试直接使用dict键。您可以创建一个dict子类,在其中您可以将键作为属性访问,类似于pandas允许作为属性或使用常规dict __getitem__
机制访问列的方式。例如
class AttributeDict(dict):
"""Access keys as attributes."""
@classmethod
def _forbidden(cls, key):
"""Key not allowed if it matches a class (not instance) attribute."""
return key in dir(cls)
def __setitem__(self, key, val):
"""Regular dict setitem + attribute set."""
# key must be a regular python identifier, in order to be accesible as
# an attribute.
if not str.isidentifier(key):
raise ValueError("'%s' it not a valid Python identifier. "
"Cannot set attribute." % key)
# Prevent accidentally overwriting an important class attribute.
if self._forbidden(key):
raise ValueError("Key '%s' is a class attribute" % key)
super().__setitem__(key, val)
setattr(self, key, val)
def __delitem__(self, key):
"""Regular dict delitem + attribute removal."""
super().__delitem__(key)
delattr(self, key)
该类尚未完成,因为它不会阻止直接设置属性,而该属性可能会使dict键值不同步。
In [4]: x = AttributeDict()
In [5]: x['A'] = 1
In [6]: x['2A'] = 1
ValueError: '2A' it not a valid Python identifier. Cannot set attribute.
In [7]: x['B'] = 2
In [8]: x.A
Out[8]: 1
In [9]: x.B
Out[9]: 2
您的特定用例如下:
dfs = AttributeDict()
for x in files:
dfs[x] = pd.read_csv(x)
dfs.file1
dfs.file2
现在,要回答原始问题,您可以使用locals()
。
for x in files:
if not str.isidentifier(x):
raise ValueError("'%s' not a valid identifier." % x)
locals()[x] = pd.read_csv(x)
文件名是有效的标识符,但与重要的本地变量冲突将造成严重破坏!例如,如果您正在IPython会话中并且执行locals()['exit'] = None
,则可以再使用exit
命令!