Python 文件转换需要 2 天以上的时间

Python file conversion takes more than 2 days

我有一个文件夹,其中包含大约 400 个 txt 文件。 txt 文件的最大大小为 2 到 2.5 mb。

我正在尝试使用 python 代码将这些文件转换为 csv。当我的 txt 文件很小(甚至超过 500 个文件)时,我的代码可以完美地工作并快速将 txt 转换为 csv 但是当文件很小时需要很长时间。

很明显,大量数据需要很长时间,但问题是我 运行 这个转换过程已经 2 天了,甚至还没有完成 50%。

有什么办法可以快速将这些 txt 文件转换为 csv 文件吗??我的意思是几个小时后。 如果超过2天,我就没有足够的时间分析了。

我的代码在这里:

import glob
import os, os.path, glob
import numpy as np
import matplotlib.pyplot as plt
from natsort import natsorted
import pandas as pd
from matplotlib.patches import Ellipse
from matplotlib.text import OffsetFrom


from mpl_toolkits.mplot3d import Axes3D
from random import random

data_folder = "./all/"
data_folder
files = natsorted(glob.glob(data_folder + 'dump*.data'))
number_of_files = len(files)
#print(number_of_files)
#files

file_open = open("./all/dump80000.data", "r")
with open("./all/dump80000.data") as f:
  lines = f.readlines()
#removing 'ITEM:' 
s = 'ITEM: ATOMS '
lines[8] = lines[8].replace(s, '')

#getting the header names
headers = lines[8].split()

headers.append('TIMESTEP')
df = pd.DataFrame(columns=headers)

counter = 0
for total_files in range(number_of_files):
    with open(files[total_files]) as f:
        lines = f.readlines()
        total_atoms = int(lines[3])
        for i in range(total_atoms):
            row_elements = lines[9+i].split()
            row_elements.append(int(lines[1]))
            df.loc[counter] = row_elements
            counter=counter+1

    df.to_csv(r'all.csv', index = False)

有什么想法吗?建议?

谢谢

以防万一,如果您需要txt样本:

https://raw.githubusercontent.com/Laudarisd/dump46000.data

https://raw.githubusercontent.com/Laudarisd/test/main/dump46000.data

快速浏览一下您的代码,您似乎正在采用以下方法来转换文件:

  1. 打开文件
  2. 将整个文件读入缓冲区
  3. 处理缓冲区

但是,如果您可以对代码进行一些小的调整:

  1. 打开文件
  2. 读一行
  3. 处理行
  4. 继续直到文件完成

基本上,采用迭代方法而不是一次读取整个文件。接下来,您可以使用 asyncio 使其更快,您可以在其中同时处理所有文件。

如果不知道你想从这些文件中提取什么数据,很难给出精确的帮助,但乍一看你肯定应该使用 pandas 的内置文件读取方法之一,保证比你的代码快很多倍。假设您希望跳过前 9 行,您可以这样做:

headers = ["a", "b", ...]
pd.read_csv(open("./all/dump80000.data"), skiprows=9, sep=" ", columns=headers)

如果这仍然不够快,您可以并行化您的代码,因为大部分处理只是将数据加载到内存中。

使用简单的 readline 怎么样?我怀疑 readlines and/or pd.DataFrame 耗费了太多时间。以下似乎对我来说足够快了。

import glob
import time

start = time.time()

data_folder = "./all/"
files = glob.glob(data_folder + 'dump*.data')

# get header from one of the files
with open('all/dump46000.data', 'r') as f:
    for _ in range(8):
        next(f) # skip first 8 lines
    header = ','.join(f.readline().split()[2:]) + '\n'

for file in files:
    with open(file, 'r') as f, open(f'all.csv', 'a') as g: # note the 'a'
        g.write(header) # write the header
        for _ in range(9):
            next(f) # skip first 9 lines
        for line in f:
            g.write(line.rstrip().replace(' ', ',') + '\n')

print(time.time() - start)

# id,type,x,y,z,vx,vy,vz,fx,fy,fz
# 201,1,0.00933075,-0.195667,1.53332,-0.000170702,-0.000265168,0.000185569,0.00852572,-0.00882728,-0.0344813
# 623,1,-0.101572,-0.159675,1.52102,-0.000125008,-0.000129469,6.1561e-05,0.0143586,-0.0020444,-0.0400259
# 851,1,-0.0654623,-0.176443,1.52014,-0.00017815,-0.000224676,0.000329338,0.0101743,0.00116504,-0.0344114
# 159,1,-0.0268728,-0.186269,1.51979,-0.000262947,-0.000386994,0.000254515,0.00961213,-0.00640215,-0.0397847

我建议将问题分解为几个文件的不同步骤,然后一旦您确定了解如何正确地独立编码每个步骤,您就可以考虑将它们组合起来:

  1. 将所有 TXT 转换为 CSV
  2. 按照您的需要处理每个 CSV

步骤 1 的操作方法如下:

import csv

out_f =  open('output.csv', 'w', newline='')
writer = csv.writer(out_f)
in_f = open('input.txt')

# Consume first 8 lines you don't want
for _ in range(8):
    next(in_f)

# Get and fix-up your header
header = next(in_f).replace('ITEM: ATOMS ', '')
writer.writerow(header.split())

# Read the rest of the file line-by-line, splitting by space, which will make a row that the CSV writer can write
for line in in_f:
    row = line.split()
    writer.writerow(row)

in_f.close()
out_f.close()

当我 运行 针对您的样本 .data 文件时,我得到:

id,type,x,y,z,vx,vy,vz,fx,fy,fz
201,1,0.00933075,-0.195667,1.53332,-0.000170702,-0.000265168,0.000185569,0.00852572,-0.00882728,-0.0344813
623,1,-0.101572,-0.159675,1.52102,-0.000125008,-0.000129469,6.1561e-05,0.0143586,-0.0020444,-0.0400259
851,1,-0.0654623,-0.176443,1.52014,-0.00017815,-0.000224676,0.000329338,0.0101743,0.00116504,-0.0344114
...

对所有 400 个 TXT 文件执行此操作,然后编写另一个脚本来处理生成的 CSV。

我使用的是 M1 Macbook Air,配备优质、快速的 SSD。转换一个 .data 文件只需不到一点点的时间。除非你有一个非常慢的磁盘,否则我看不到这两个步骤都需要一个多小时。