下面是使用 re 解析文件的优化方法,首先获取 ID,然后解析数据元组。 这利用了文件对象可迭代的事实 当迭代打开的文件时,可以将单独的行作为字符串,从中可以提取有意义的数据元素。import re
import pandas as pd
SEP_RE = re.compile(r":s+")
DATA_RE = re.compile(r"(?P[a-z]+)s+(?Pd+.d+)", re.I)
def parse(filepath: str):
def _parse(filepath):
with open(filepath) as f:
for line in f:
id, rest = SEP_RE.split(line, maxsplit=1)
for match in DATA_RE.finditer(rest):
yield [int(id), match["term"], float(match["weight"])]
return list(_parse(filepath))
例如:>>> df = pd.DataFrame(parse("/Users/bradsolomon/Downloads/doc.txt"),
... columns=["Id","Term","weight"])
>>>
>>> df
Id Term weight
0 1 frack 0.733
1 1 shale 0.700
2 10 space 0.645
3 10 station 0.327
4 10 nasa 0.258
5 4 celebr 0.262
6 4 bahar 0.345
>>> df.dtypes
Id int64
Term object
weight float64
dtype: object
演练
SEP_RE 查找初始分隔符: 文本 : 后跟一个或多个空格。 它使用 maxsplit=1 在第一次分割时停止。 当然,这假定你的数据的格式为 formatted: 整个数据集的格式始终遵循在你的问题中设置的示例格式。
之后,DATA_RE.finditer() 处理来自 rest的每个( , ) 对 extraxted 。 字符串 rest 本身看起来像 frack 0.733, shale 0.700, 。 .finditer() 为你提供了多个 match 对象你可以使用 ["key"] 表示法从给定的 命名捕获组 例如 (?P[a-z]+) 访问该元素 。
可视化的一种简单方法是使用文件中的示例 line 作为字符串:>>> line ="1: frack 0.733, shale 0.700,n"
>>> SEP_RE.split(line, maxsplit=1)
['1', 'frack 0.733, shale 0.700,n']
现在你有了组件的初始标识和其他组件,你可以将它们解压到两个标识符中。>>> id, rest = SEP_RE.split(line, maxsplit=1)
>>> it = DATA_RE.finditer(rest)
>>> match = next(it)
>>> match
>>> match["term"]
'frack'
>>> match["weight"]
'0.733'
更好的可视化方法是使用 pdb 。 如果你敢的话,试试吧。
免责声明
这是需要特定类型的解决方案的问题之一,如果你放宽对数据格式的限制,这些问题可能无法很好地概括 。
例如它假设每个 Term 只能采用大写或小写的ASCII字母,没有别的 。 如果你有其他Unicode字符作为标识符,你将希望查看其他 re 字符,如 w 。