blu*_*e13 39 python regex performance parsing pandas
我有许多文本文件,比如50,我需要读入一个庞大的数据帧.目前,我正在使用以下步骤.
这适用于100 KB大小的文件 - 几分钟,但在50 MB时,它只需要几个小时,并且不实用.
如何优化我的代码?特别是 -
这是一个示例代码.我自己的代码有点复杂,因为文本文件更复杂,因此我必须使用大约10个正则表达式和多个while循环来读取数据并将其分配到正确数组中的正确位置.为了保持MWE的简单,我没有在MWE的输入文件中使用重复标签,所以我希望我无缘无故地读取文件两次.我希望这是有道理的!
import re
import pandas as pd
df = pd.DataFrame()
paths = ["../gitignore/test1.txt", "../gitignore/test2.txt"]
reg_ex = re.compile('^(.+) (.+)\n')
# read all files to determine what indices are available
for path in paths:
file_obj = open(path, 'r')
print file_obj.readlines()
['a 1\n', 'b 2\n', 'end']
['c 3\n', 'd 4\n', 'end']
indices = []
for path in paths:
index = []
with open(path, 'r') as file_obj:
line = True
while line:
try:
line = file_obj.readline()
match = reg_ex.match(line)
index += match.group(1)
except AttributeError:
pass
indices.append(index)
# read files again and put data into a master dataframe
for path, index in zip(paths, indices):
subset_df = pd.DataFrame(index=index, columns=["Number"])
with open(path, 'r') as file_obj:
line = True
while line:
try:
line = file_obj.readline()
match = reg_ex.match(line)
subset_df.loc[[match.group(1)]] = match.group(2)
except AttributeError:
pass
df = pd.concat([df, subset_df]).sort_index()
print df
Number
a 1
b 2
c 3
d 4
Run Code Online (Sandbox Code Playgroud)
我的输入文件:
test1.txt的
a 1
b 2
end
Run Code Online (Sandbox Code Playgroud)
的test2.txt
c 3
d 4
end
Run Code Online (Sandbox Code Playgroud)
clo*_*ker 16
在拔出多处理锤之前,您的第一步应该是进行一些分析.使用cProfile快速查看以确定哪些功能需要很长时间.不幸的是,如果你的行都在一个函数调用中,它们将显示为库调用.line_profiler更好,但需要更多的设置时间.
注意.如果使用ipython,您可以使用%timeit(timeit模块的magic命令)和%prun(profile模块的magic命令)来为语句和函数计时.谷歌搜索将显示一些指南.
熊猫是一个很棒的图书馆,但是我偶尔也会因为结果糟糕而使用它.特别要注意append()/ concat()操作.这可能是你的瓶颈,但你应该确定一下.通常,如果您不需要执行索引/列对齐,则numpy.vstack()和numpy.hstack()操作会更快.在你的情况下,看起来你可以使用系列或1-D numpy ndarray,这可以节省时间.
顺便说一句,trypython中的一个块通常比检查无效条件慢10倍或更多,所以当你将它粘贴到每一行的循环中时,确保你绝对需要它.这可能是时间的另一个障碍; 我想你在try.group(1)失败的情况下卡住了try块来检查AttributeError.我会先检查一下有效的比赛.
即使是这些小的修改也应该足以让你的程序在尝试像多处理这样繁琐的事情之前运行得更快.那些Python库非常棒,但却带来了一系列新的挑战.
Нек*_*кто 15
我已经多次使用它,因为它是多处理的一个特别简单的实现.
import pandas as pd
from multiprocessing import Pool
def reader(filename):
return pd.read_excel(filename)
def main():
pool = Pool(4) # number of cores you want to use
file_list = [file1.xlsx, file2.xlsx, file3.xlsx, ...]
df_list = pool.map(reader, file_list) #creates a list of the loaded df's
df = pd.concat(df_list) # concatenates all the df's into a single df
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
使用它你应该能够大大提高你的程序的速度,而不需要太多的工作.如果您不知道有多少处理器,可以通过拉起shell并键入来检查
echo %NUMBER_OF_PROCESSORS%
Run Code Online (Sandbox Code Playgroud)
编辑:为了使这个运行更快,考虑将文件更改为csvs并使用pandas函数pandas.read_csv
事实证明,首先创建一个空白的 DataFrame,搜索索引以找到一行数据的正确位置,然后仅更新 DataFrame 的一行是一个非常耗时的过程。
一种更快的方法是将输入文件的内容读取到原始数据结构(例如列表列表或字典列表)中,然后将其转换为 DataFrame。
当您读取的所有数据都位于同一列中时,请使用列表。否则,使用字典明确说明每一位数据应该进入哪一列。
1 月 18 日更新:这链接到如何使用 Python 解析复杂的文本文件?我还写了一篇博客文章,向初学者解释如何解析复杂文件。