在带有冒号分隔数字的文本文件上使用numpy.fromregex

时间:2017-11-13 21:16:16

标签: python regex numpy

我有一个如下所示的数据集:

# sparse.txt
1 1:1 2:1 3:1
0 1:1 4:1
1 12:1 13:1 14:1

我想创建一个没有冒号的矩阵,如下所示:

# sparse2.txt
1 1 1 2 1 3 1
0 1 1 4 1
1 2 1 3 1 4 1

我使用在线python正则表达式来查找正则表达式模式来读取文件的行。 https://pythex.org/

我使用了模式:

pat = [0-1]\s+([0-9]:1\s*)+

哪个满足在线regexer中的正则表达式,但是,当我在np.fromregex中使用它时 它不起作用。

import numpy as np
pat = r'[0-1]\s+([0-9]:1\s*)+'

data = np.fromregex('sparse.txt', pat, dtype='str')
print("data = {}".format(data))

我们如何修复错误?

2 个答案:

答案 0 :(得分:0)

出了什么问题

<强> [0-1]\s+([0-9]:1\s*)+

  • 这将匹配整行,而不是您想要的每个数字enter image description here

如何解决?

import numpy as np
pat = r'^\d|[^0-9\:\n][\d]?'

data = np.fromregex('sparse.txt', pat, [('num', np.int64)])
print("data = {}".format(data))

结果

enter image description here

建议

  • 使用SublimeText帮助您撰写正则表达式
  • numpy.fromregex官方参考link

答案 1 :(得分:0)

使用@ Wiktor的模式

In [58]: pat1 = r'([0-1])\s+([0-9]):(1)\s+([0-9]):(1)(?:\s+([0-9]):(1))?'
In [59]: np.fromregex('stack47266965.txt', pat1, dtype='str')
Out[59]: 
array([['1', '1', '1', '2', '1', '3', '1'],
       ['0', '1', '1', '4', '1', '', ''],
       ['1', '2', '1', '3', '1', '4', '1']],
      dtype='<U1')

这是一个dd字符串的二维数组(这里是unicode);注意第二行短的填充。这是由模式的?:部分产生的。

fromregex执行re.findall并将该元组列表转换为数组:

In [60]: re.findall(pat1, open('stack47266965.txt').read())
Out[60]: 
[('1', '1', '1', '2', '1', '3', '1'),
 ('0', '1', '1', '4', '1', '', ''),
 ('1', '2', '1', '3', '1', '4', '1')]

请注意,fromregex文档强调它返回structured array。该元组列表可以是np.array(seq, dtype=dt)的正确输入,其中dt是复合dtype。每个元组应该具有相同的长度,一个与dtype匹配。

此案例表明它适用于像str这样的简单dtype。但这对你有什么用呢。你不能将这些字符串转换为数字,而不会以某种方式过滤空白。没有空白,阵列不能再是2d。那条短的中间线阻止了这一点。

numpy中的文本文件读取器旨在逐行读取文件,将每个文件解析为2d数组的行或1d结构化数组的记录。不规则的线长是一个问题,需要某种填充。

@ XetRAFHan的模式会提取您想要的所有数字,但会丢失行结构:

In [93]: pat2 = r'^\d|[^0-9\:\n][\d]?'
In [94]: re.findall(pat2, open('stack47266965.txt').read())
Out[94]: ['1', ' 1', ' 2', ' 3', ' 1', ' 4', ' 2', ' 3', ' 4']

您在保留文件结构之前所做的拆分

Create dense matrix from sparse matrix efficently (numpy/scipy but NO sklearn)

In [95]: lines = open('stack47266965.txt').readlines()
In [96]: lines
Out[96]: ['1 1:1 2:1 3:1\n', '0 1:1 4:1\n', '1 2:1 3:1 4:1\n']
In [97]: alist = []
In [98]: for line in lines:
    ...:     row = line.split()
    ...:     label = int(row[0])
    ...:     values = [int(a.split(':')[0]) for a in row[1:]]
    ...:     alist.append((label, values))
    ...:     
In [99]: alist
Out[99]: [(1, [1, 2, 3]), (0, [1, 4]), (1, [2, 3, 4])]