【问题标题】:Read multiple txt and create df for each with names from original files读取多个 txt 并为每个使用原始文件的名称创建 df
【发布时间】:2019-11-15 12:46:27
【问题描述】:

文件夹有五个或六个 .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)

这可行,但完整路径的命名并不理想。

【问题讨论】:

    标签: python-3.x pandas csv


    【解决方案1】:

    如果您的文件名不是来自网络等不受信任的来源,请使用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))
    

    如果文件名不可信,请不要这样做,因为文件名中的任何代码都会被执行。

    【讨论】:

      【解决方案2】:

      您正在尝试做的事情 - 创建与文件同名的动态局部变量是我不经常遇到的模式,并且可能会出现问题,但是我已经展示了一种方法下面也是。您应该尝试直接使用 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 命令!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-16
        • 1970-01-01
        • 1970-01-01
        • 2019-03-09
        • 2022-01-04
        相关资源
        最近更新 更多