Python 使用re(正则表达式)只解析行的块
我的实验室正在使用一个软件,该软件会生成大量的数据作为输出,所以我正在尝试使用Python使事情变得更简单。到目前为止,我认为最好的方法是生成列表并将其视为数据块,但这并不容易: 第一块数据很简单:3列是固定的,只需使用以下方法即可获得:Python 使用re(正则表达式)只解析行的块,python,python-3.x,pandas,dataframe,Python,Python 3.x,Pandas,Dataframe,我的实验室正在使用一个软件,该软件会生成大量的数据作为输出,所以我正在尝试使用Python使事情变得更简单。到目前为止,我认为最好的方法是生成列表并将其视为数据块,但这并不容易: 第一块数据很简单:3列是固定的,只需使用以下方法即可获得: chunk1 = my_data[:3] 第二块数据并不容易,因为它可以有2、3或4列。我相信这里的关键是,当我们找到一个类似于137CCC的字母时,第二段就结束了。在这种情况下,我相信可以使用re模块解析两列、三列或四列,并在第一个字母之前停止,但我不知道
chunk1 = my_data[:3]
第二块数据并不容易,因为它可以有2、3或4列。我相信这里的关键是,当我们找到一个类似于137CCC的字母时,第二段就结束了。在这种情况下,我相信可以使用re模块解析两列、三列或四列,并在第一个字母之前停止,但我不知道如何做。我打算通过用零或“-”填充空白点来“规范化”这些列,因此如果我有2列的情况,我将用[x,y,0,0]填充它,用[x,y,z,0]填充3列的情况
第三块是固定的两个、三个或四个字母和一个数字,如:CCC119.62
第四块是剩下的
下面是混乱输出的表示:
最终结果可能是:
[s 91,1.00,OUT][9,3,12,7][OCCC,0.34][f829,27,f752,33]
到目前为止,我一直在想如何让re模块像这样工作:
text = """s 27 1.00 STRE 30 16 OC 1.355049 f1291 50
s 34 -1.00 BEND 1 3 7 CCC 119.62 f1037 26 f485 10
s 89 1.00 TORS 31 30 16 19 COCC 0.24 f161 14 f104 46 f87 19 f43 10
s 91 1.00 OUT 9 3 12 7 OCCC 0.34 f829 27 f752 33"""
my_file = StringIO(text)
chunks = []
for line in my_file:
my_data = line.split()
chunk1 = my_data[:4]
chunk2 = my_data[4:6]
for i in range(6, 8):
if my_data[i].isdigit():
chunk2.append(my_data[i])
else:
break
chunk3_start = len(chunk1) + len(chunk2)
chunk3 = my_data[chunk3_start:chunk3_start+2]
chunk4 = my_data[chunk3_start+2:]
chunks.append({1: chunk1, 2: chunk2, 3: chunk3, 4: chunk4})
非常感谢你们的帮助,伙计们
数据样本
这个问题不需要正则表达式。您可以这样做:
text = """s 27 1.00 STRE 30 16 OC 1.355049 f1291 50
s 34 -1.00 BEND 1 3 7 CCC 119.62 f1037 26 f485 10
s 89 1.00 TORS 31 30 16 19 COCC 0.24 f161 14 f104 46 f87 19 f43 10
s 91 1.00 OUT 9 3 12 7 OCCC 0.34 f829 27 f752 33"""
my_file = StringIO(text)
chunks = []
for line in my_file:
my_data = line.split()
chunk1 = my_data[:4]
chunk2 = my_data[4:6]
for i in range(6, 8):
if my_data[i].isdigit():
chunk2.append(my_data[i])
else:
break
chunk3_start = len(chunk1) + len(chunk2)
chunk3 = my_data[chunk3_start:chunk3_start+2]
chunk4 = my_data[chunk3_start+2:]
chunks.append({1: chunk1, 2: chunk2, 3: chunk3, 4: chunk4})
将生成以下输出:
[{1: ['s', '27', '1.00', 'STRE'],
2: ['30', '16'],
3: ['OC', '1.355049'],
4: ['f1291', '50']},
{1: ['s', '34', '-1.00', 'BEND'],
2: ['1', '3', '7'],
3: ['CCC', '119.62'],
4: ['f1037', '26', 'f485', '10']},
{1: ['s', '89', '1.00', 'TORS'],
2: ['31', '30', '16', '19'],
3: ['COCC', '0.24'],
4: ['f161', '14', 'f104', '46', 'f87', '19', 'f43', '10']},
{1: ['s', '91', '1.00', 'OUT'],
2: ['9', '3', '12', '7'],
3: ['OCCC', '0.34'],
4: ['f829', '27', 'f752', '33']}]
基本上,你一直在向chunk2添加元素,直到你遇到一些不是数字的东西。使用chunk1和chunk2的长度来获取剩余的块。这个问题不需要正则表达式。您可以这样做:
text = """s 27 1.00 STRE 30 16 OC 1.355049 f1291 50
s 34 -1.00 BEND 1 3 7 CCC 119.62 f1037 26 f485 10
s 89 1.00 TORS 31 30 16 19 COCC 0.24 f161 14 f104 46 f87 19 f43 10
s 91 1.00 OUT 9 3 12 7 OCCC 0.34 f829 27 f752 33"""
my_file = StringIO(text)
chunks = []
for line in my_file:
my_data = line.split()
chunk1 = my_data[:4]
chunk2 = my_data[4:6]
for i in range(6, 8):
if my_data[i].isdigit():
chunk2.append(my_data[i])
else:
break
chunk3_start = len(chunk1) + len(chunk2)
chunk3 = my_data[chunk3_start:chunk3_start+2]
chunk4 = my_data[chunk3_start+2:]
chunks.append({1: chunk1, 2: chunk2, 3: chunk3, 4: chunk4})
将生成以下输出:
[{1: ['s', '27', '1.00', 'STRE'],
2: ['30', '16'],
3: ['OC', '1.355049'],
4: ['f1291', '50']},
{1: ['s', '34', '-1.00', 'BEND'],
2: ['1', '3', '7'],
3: ['CCC', '119.62'],
4: ['f1037', '26', 'f485', '10']},
{1: ['s', '89', '1.00', 'TORS'],
2: ['31', '30', '16', '19'],
3: ['COCC', '0.24'],
4: ['f161', '14', 'f104', '46', 'f87', '19', 'f43', '10']},
{1: ['s', '91', '1.00', 'OUT'],
2: ['9', '3', '12', '7'],
3: ['OCCC', '0.34'],
4: ['f829', '27', 'f752', '33']}]
基本上,你一直在向chunk2添加元素,直到你遇到一些不是数字的东西。使用chunk1和chunk2的长度来获取剩余的块。我编写了一个生成器,从迭代器中提取,直到找到alpha字符串
from itertools import chain
def while_not_alpha(iterator):
iterator = iter(iterator)
for s in iterator:
if not str(s).isalpha():
yield s
else:
yield chain([s], iterator)
break
def parse(line):
*chunk1, rest = line.split(maxsplit=4)
*chunk2, rest = while_not_alpha(rest.split())
rest = list(rest)
chunk3 = rest[:2]
chunk4 = rest[2:]
return chunk1, chunk2, chunk3, chunk4
# See below for definition of `txt`
chunk1, chunk2, chunk3, chunk4 = map(list, zip(*map(parse, txt.splitlines())))
我们可以看到chunk2看起来像
chunk2[:4]
[['30', '16'],
['8', '6'],
['14', '15'],
['14', '15']]
和chunk3
我们本可以更进一步制作数据帧
chunk1, chunk2, chunk3, chunk4 = map(
pd.DataFrame, map(list, zip(*map(parse, txt.splitlines()))))
chunk2.head()
0 1 2 3
0 30 16 None None
1 8 6 None None
2 14 15 None None
3 14 15 None None
4 8 6 None None
5 30 31 None None
6 13 11 None None
7 1 3 7 None
8 3 1 4 None
9 7 3 1 None
10 21 14 15 None
11 24 5 2 None
12 25 2 6 None
13 24 5 2 None
14 25 2 6 None
15 26 19 18 None
16 31 30 16 19
17 8 2 3 6
18 9 3 12 7
或者更进一步:
df = pd.concat(
map(pd.DataFrame, map(list, zip(*map(parse, txt.splitlines())))),
axis=1, keys=[f'chunk{i}' for i in range(1, 5)]
)
df
chunk1 chunk2 chunk3 chunk4
0 1 2 3 0 1 2 3 0 1 0 1 2 3 4 5 6 7
0 s 27 1.00 STRE 30 16 None None OC 1.355049 f1291 50 None None None None None None
1 s 28 -1.00 STRE 8 6 None None CC 1.494281 f1340 12 f1271 17 None None None None
2 s 29 -1.00 STRE 14 15 None None NC 1.421282 f1358 49 None None None None None None
3 s 30 1.00 STRE 14 15 None None NC 1.421282 f1337 10 f1290 33 None None None None
4 s 31 1.00 STRE 8 6 None None CC 1.494281 f1171 15 f323 11 None None None None
5 s 32 1.00 STRE 30 31 None None OC 1.419982 f1082 51 f1077 24 None None None None
6 s 33 1.00 STRE 13 11 None None ClC 1.740581 f842 15 f323 19 None None None None
7 s 34 -1.00 BEND 1 3 7 None CCC 119.62 f1037 26 f485 10 None None None None
8 s 35 -1.00 BEND 3 1 4 None CCC 119.74 f1124 29 None None None None None None
9 s 36 1.00 BEND 7 3 1 None CCC 119.62 f733 25 f288 13 None None None None
10 s 37 1.00 BEND 21 14 15 None HNC 116.16 f1578 40 f1560 20 None None None None
11 s 38 1.00 BEND 24 5 2 None HCC 119.73 f1186 67 None None None None None None
12 s 39 1.00 BEND 25 2 6 None HCC 118.80 f1536 53 f1082 10 f1077 17 None None
13 s 40 -1.00 BEND 24 5 2 None HCC 119.73 f1508 44 f1171 14 f1124 13 None None
14 s 41 1.00 BEND 25 2 6 None HCC 118.80 f1669 14 f1271 32 f1124 15 None None
15 s 42 -1.00 BEND 26 19 18 None HCC 119.04 f1578 10 f1560 37 f1291 11 None None
16 s 89 1.00 TORS 31 30 16 19 COCC 0.24 f161 14 f104 46 f87 19 f43 10
17 s 90 1.00 OUT 8 2 3 6 CCCC 1.09 f466 36 f125 22 None None None None
18 s 91 1.00 OUT 9 3 12 7 OCCC 0.34 f829 27 f752 33 None None None None
设置
我编写了一个生成器,它从迭代器中提取,直到找到一个alpha字符串
from itertools import chain
def while_not_alpha(iterator):
iterator = iter(iterator)
for s in iterator:
if not str(s).isalpha():
yield s
else:
yield chain([s], iterator)
break
def parse(line):
*chunk1, rest = line.split(maxsplit=4)
*chunk2, rest = while_not_alpha(rest.split())
rest = list(rest)
chunk3 = rest[:2]
chunk4 = rest[2:]
return chunk1, chunk2, chunk3, chunk4
# See below for definition of `txt`
chunk1, chunk2, chunk3, chunk4 = map(list, zip(*map(parse, txt.splitlines())))
我们可以看到chunk2看起来像
chunk2[:4]
[['30', '16'],
['8', '6'],
['14', '15'],
['14', '15']]
和chunk3
我们本可以更进一步制作数据帧
chunk1, chunk2, chunk3, chunk4 = map(
pd.DataFrame, map(list, zip(*map(parse, txt.splitlines()))))
chunk2.head()
0 1 2 3
0 30 16 None None
1 8 6 None None
2 14 15 None None
3 14 15 None None
4 8 6 None None
5 30 31 None None
6 13 11 None None
7 1 3 7 None
8 3 1 4 None
9 7 3 1 None
10 21 14 15 None
11 24 5 2 None
12 25 2 6 None
13 24 5 2 None
14 25 2 6 None
15 26 19 18 None
16 31 30 16 19
17 8 2 3 6
18 9 3 12 7
或者更进一步:
df = pd.concat(
map(pd.DataFrame, map(list, zip(*map(parse, txt.splitlines())))),
axis=1, keys=[f'chunk{i}' for i in range(1, 5)]
)
df
chunk1 chunk2 chunk3 chunk4
0 1 2 3 0 1 2 3 0 1 0 1 2 3 4 5 6 7
0 s 27 1.00 STRE 30 16 None None OC 1.355049 f1291 50 None None None None None None
1 s 28 -1.00 STRE 8 6 None None CC 1.494281 f1340 12 f1271 17 None None None None
2 s 29 -1.00 STRE 14 15 None None NC 1.421282 f1358 49 None None None None None None
3 s 30 1.00 STRE 14 15 None None NC 1.421282 f1337 10 f1290 33 None None None None
4 s 31 1.00 STRE 8 6 None None CC 1.494281 f1171 15 f323 11 None None None None
5 s 32 1.00 STRE 30 31 None None OC 1.419982 f1082 51 f1077 24 None None None None
6 s 33 1.00 STRE 13 11 None None ClC 1.740581 f842 15 f323 19 None None None None
7 s 34 -1.00 BEND 1 3 7 None CCC 119.62 f1037 26 f485 10 None None None None
8 s 35 -1.00 BEND 3 1 4 None CCC 119.74 f1124 29 None None None None None None
9 s 36 1.00 BEND 7 3 1 None CCC 119.62 f733 25 f288 13 None None None None
10 s 37 1.00 BEND 21 14 15 None HNC 116.16 f1578 40 f1560 20 None None None None
11 s 38 1.00 BEND 24 5 2 None HCC 119.73 f1186 67 None None None None None None
12 s 39 1.00 BEND 25 2 6 None HCC 118.80 f1536 53 f1082 10 f1077 17 None None
13 s 40 -1.00 BEND 24 5 2 None HCC 119.73 f1508 44 f1171 14 f1124 13 None None
14 s 41 1.00 BEND 25 2 6 None HCC 118.80 f1669 14 f1271 32 f1124 15 None None
15 s 42 -1.00 BEND 26 19 18 None HCC 119.04 f1578 10 f1560 37 f1291 11 None None
16 s 89 1.00 TORS 31 30 16 19 COCC 0.24 f161 14 f104 46 f87 19 f43 10
17 s 90 1.00 OUT 8 2 3 6 CCCC 1.09 f466 36 f125 22 None None None None
18 s 91 1.00 OUT 9 3 12 7 OCCC 0.34 f829 27 f752 33 None None None None
设置
这是我的变体:
def simple_parsing(string):
from re import split
parts = split('\s+',string)
result = [];i=4
while not parts[i].isalpha():
result.append(parts[i])
i+=1
return([parts[0:4],result,parts[i:i+2],parts[i+2:]])
例如,以您的一个字符串为例,结果如下:
simple_parsing('s 91 1.00 OUT 9 3 12 7 OCCC 0.34 f829 27 f752 33')
[['s', '91', '1.00', 'OUT'], ['9', '3', '12', '7'], ['OCCC', '0.34'], ['f829', '27', 'f752', '33']]
这是我的变体:
def simple_parsing(string):
from re import split
parts = split('\s+',string)
result = [];i=4
while not parts[i].isalpha():
result.append(parts[i])
i+=1
return([parts[0:4],result,parts[i:i+2],parts[i+2:]])
例如,以您的一个字符串为例,结果如下:
simple_parsing('s 91 1.00 OUT 9 3 12 7 OCCC 0.34 f829 27 f752 33')
[['s', '91', '1.00', 'OUT'], ['9', '3', '12', '7'], ['OCCC', '0.34'], ['f829', '27', 'f752', '33']]
第一个错误是下意识地想到正则表达式。只要读一行,把它分成几个部分,然后根据内容进一步处理。当然,您可以使用正则表达式,它们甚至可以帮助验证行,但使用它们本身不应该是一个目标。第一个错误是考虑正则表达式时的下意识反应。只要读一行,把它分成几个部分,然后根据内容进一步处理。当然,您可以使用正则表达式,它们甚至可以帮助验证行,但使用它们本身不应该是一个目标。谢谢你@piRSquared@HenriqueJunior你这么说真是太好了。不用客气。我对这个解决方案有多优雅感到困惑。谢谢你@piRSquared@HenriqueJunior你这么说真是太好了。不客气。谢谢你的建议。谢谢你的建议。谢谢你的建议。谢谢你,@pault,这是一个非常优雅的方法。谢谢你,@pault,这是一个非常优雅的方法。