当前位置: 首页 > 知识库问答 >
问题:

如何在过滤和添加文件名的同时加快导入许多csv的速度?

张炳
2023-03-14

我有一些执行以下操作的Python(3.8)代码:

  1. 遍历给定路径的目录和子目录
  2. 查找所有.csv文件
  3. 查找文件名中带有“Pct”的所有.csv文件
  4. 联接路径和文件
  5. 读取 CSV 格式
  6. 将文件名添加到 df
  7. 将所有 dfs 放在一起

下面的代码可以工作,但需要很长时间(15分钟)才能摄取所有CSV - 有52,000个文件。这实际上可能不是很长一段时间,但我想尽可能地减少这种情况。

我目前的工作代码如下:

start_dirctory='/home/ubuntu/Desktop/noise_paper/part_2/Noise/Data/'  # change this
df_result= None
#loop_number = 0

for path, dirs, files in os.walk(start_dirctory):
        for file in sorted(fnmatch.filter(files, '*.csv')): # find .csv files
            # print(file)
            if 'Pct' in file: # filter if contains 'Pct'
                # print('Pct = ', file)
                full_name=os.path.join(path, file) # make full file path
                df_tmp= pd.read_csv(full_name, header=None) # read file to df_tmp
                df_tmp['file']=os.path.basename(file) # df.file = file name
                if df_result is None:
                    df_result= df_tmp
                else:
                    df_result= pd.concat([df_result, df_tmp], axis='index', ignore_index=True)
                #print(full_name, 'imported')
                #loop_number = loop_number + 1
                #print('Loop number =', loop_number)

受这篇文章(递归查找文件)和这篇文章(如何加快导入csvs)的启发,我试图减少摄取所有数据所需的时间,但找不到一种方法来集成仅包含“Pct”的文件名的文件夹,然后将文件名添加到df中。这可能无法通过这些示例中的代码实现。

我在下面尝试了什么(不完整):

%%time

import glob
import pandas as pd

df = pd.concat(
    [pd.read_csv(f, header=None)
     for f in glob.glob('/home/ubuntu/Desktop/noise_paper/part_2/Noise/Data/**/*.csv', recursive=True)
    ],
    axis='index', ignore_index=True
 )

问题

有没有什么方法可以减少阅读和摄取上面代码中CSV的时间?

谢谢!

共有1个答案

吕承望
2023-03-14

请查看以下解决方案,这假设打开文件系统限制足够高,因为这将逐个流式传输每个文件,但它必须打开每个文件才能读取标头。如果文件具有不同的列,您将在生成的文件中获取它们的超集:

from convtools import conversion as c
from convtools.contrib.tables import Table

files = sorted(
    os.path.join(path, file)
    for path, dirs, files in os.walk(start_dirctory)
    for file in files
    if "Pct" in file and file.endswith(".csv")
)

table = None
for file in files:
    table_ = Table.from_csv(file, header=True)  # assuming there's header
    if table is None:
        table = table_
    else:
        table.chain(table_)

# this will be an iterable of dicts, so consume with pandas or whatever
table.into_iter_rows(dict)  # or list, or tuple

# or just write the new file like:
# >>> table.into_csv("concatenated.csv")
# HOWEVER: into_* can only be used once, because Table
# cannot assume the incoming data stream can be read twice

如果您确定所有文件都具有相同的列(一次打开一个文件):

编辑以添加文件列

def concat_files(files):
    for file in files:
        yield from Table.from_csv(file, header=True).update(
            file=file
        ).into_iter_rows(dict)

# this will be an iterable of dicts, so consume with pandas or whatever
concat_files(files)

另外,你当然可以把Table.from_csv换成标准/其他的阅读器,但是这个阅读器适应文件,所以在大文件上通常更快。

 类似资料:
  • 问题内容: 我正在编写一个小程序,该程序创建目录中所有文件的索引。它基本上遍历磁盘上的每个文件,并将其存储到可搜索的数据库中,就像Unix的locate。问题是,由于我有大约一百万个文件,因此索引生成非常慢。 一旦生成索引,是否可以快速找到自上次运行以来已在磁盘上添加或删除了哪些文件? 编辑 :我不想监视文件系统事件。我认为风险太高而无法同步,我更喜欢进行快速重新扫描之类的操作,以快速找到添加/删

  • 我已经从一个文件夹中导入了几千个txt文件到。是否有任何方法可以创建一列,从其中导入的txt文件的文件名中添加子字符串?这是通过一个唯一的名称来标识数据帧中的每个文本文件。 文本文件命名为和son打开。我想要这样的东西: 我用来导入数据的代码如下。但是,我不知道如何通过文件名的子字符串创建列。任何帮助都将不胜感激。谢谢。

  • 问题内容: 我有几个CSV文件,如下所示: 我想在所有CSV文件中添加一个新列,使其看起来像这样: 到目前为止,我的脚本是: (Python 3.2) 但是在输出中,脚本跳过了每一行,新列中仅包含Berry: 问题答案: 这应该使您知道该怎么做: 编辑,注意在py3k中必须使用 感谢您接受答案。在这里,您有一个好处(您的工作脚本): 请注意 中的参数。默认情况下,它设置为,这就是为什么间距为两倍的

  • 问题内容: 我一直在寻找如何执行此操作,但到目前为止我还没有找到任何相关的东西,:(我可以嵌套两个函数,但是我只是想知道这是否可行吗? 目前我的JS代码: 我想一键调用两个函数,如何在angularJS中做到这一点?我认为当您添加多个类时会像在CSS中那样直接…但是不是:( 问题答案: 您有2个选择: 创建包装这两个方法的第三个方法。这样做的好处是可以减少模板中的逻辑。 否则,如果要在ng-cli

  • 问题内容: 我正在编写一个脚本,用户可以在其中选择一系列数据,然后从服务器中获取一堆图像(超过150张),然后循环通过它们来制作电影。我想知道的是在移动图像槽时加载防止滞后的最有效方法。 目前,我正在使用Ajax从服务器获取图像,并将其存储在JavaScript上的Image对象数组中。在HTML中,我有一个div标签,希望在其中放置图像。在数组中创建所有Image对象(并设置其适当的src)后,

  • 问题内容: 我有一个CSV文件,例如 我想加上引号使它像: 最快的方法是什么?我将在cronjob中实现它。 问题答案: 使用sed: