Python文件转换需要2天以上
Posted
技术标签:
【中文标题】Python文件转换需要2天以上【英文标题】:Python file conversion takes more than 2 days 【发布时间】:2021-12-29 01:23:45 【问题描述】:我有一个文件夹,其中包含大约 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
【问题讨论】:
你不是打开同一个文件两次吗? 在处理性能问题时,您应该始终做的第一件事之一就是分析您的代码。见How can you profile a Python script? 【参考方案1】:使用简单的readline
怎么样?我怀疑readlines
和/或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
【讨论】:
感谢您的回答。我在一个文件夹中有 400 多个 txt 文件。我猜想使用 with open 不会在所有文件中循环。这仅适用于一个文件,对吗? 当然可以修改为嵌入for循环中。 让我试试,谢谢。 @Codeholic 检查更新的答案。例如,这将生成./all/dump46000.data.csv
。
非常感谢,似乎它确实转换为一个 csv。我必须确认我的 txt 数据和 csv 数据。非常感谢。现在你的答案是可以接受的。【参考方案2】:
快速浏览一下您的代码,您似乎正在采用以下方法来转换文件:
-
打开文件
将整个文件读入缓冲区
处理缓冲区
但是,如果您可以对代码进行一些小的调整:
-
打开文件
读一行
处理线路
继续直到文件完成
基本上,采用迭代方法而不是一次读取整个文件。接下来,您可以使用asyncio 使其更快,您可以同时处理所有文件。
【讨论】:
你说得对,我能得到一点提示来编辑我的代码吗?这将是一个很大的帮助。【参考方案3】:如果不确切知道要从这些文件中提取哪些数据,很难提供准确的帮助,但乍一看,您绝对应该使用 pandas 的内置文件读取方法之一,该方法保证比您的文件读取速度快很多倍代码。假设您希望跳过前 9 行,您可以执行以下操作:
headers = ["a", "b", ...]
pd.read_csv(open("./all/dump80000.data"), skiprows=9, sep=" ", columns=headers)
如果这仍然不够快,您可以并行化您的代码,因为大部分处理只是将数据加载到内存中。
【讨论】:
您好,非常感谢。我在我的问题中提到了一个示例数据链接。你是对的,我想在第 9 行之后将我的数据转换为 csv。第 8 行包括所有 txt 文件中的数据标题。之后,所有行都包含有关标题的信息。【参考方案4】:我建议将问题分解为几个文件的不同步骤,然后一旦您确定了解如何正确地独立编码每个步骤,您就可以考虑将它们组合起来:
-
将所有 TXT 转换为 CSV
根据需要处理每个 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 文件只需不到一秒。除非你有一个非常慢的磁盘,否则我看不到这两个步骤都需要一个多小时。
【讨论】:
非常感谢,现在我尝试管理它。以上是关于Python文件转换需要2天以上的主要内容,如果未能解决你的问题,请参考以下文章
100天精通Python(数据分析篇)——第71天:Pandas文本数据处理方法之str/object类型转换大小写转换文本对齐获取长度出现次数编码
100天精通Python(数据分析篇)——第71天:Pandas文本数据处理方法之str/object类型转换大小写转换文本对齐获取长度出现次数编码