用python读表格数据

时间:2013-12-12 03:19:14

标签: python csv

我有一堆带有表格数据的文本文件。它看起来像这样:

 1. BRISTOL CITY             42  16  4  1  43  13   8  7  6  23  27   59
 2. Plymouth Argyle          42  18  3  0  47   6   5  4 12  14  23   53
 3. Swansea City             42  13  6  2  46  14   9  3  9  32  31   53
 4. Brighton & Hove Albion   42  15  3  3  39  13   5  8  8  13  21   51
 5. Luton Town               42  14  4  3  47  18   7  3 11  21  31   49
 6. Millwall                 42   9 10  2  27  13   5  8  8  18  27   46
 7. Portsmouth               42  10  5  6  34  20   9  3  9  24  32   46
 8. Northampton              42  13  6  2  40  17   4  5 12  14  27   45
 9. Swindon Town             42  14  4  3  41  17   3  7 11  21  39   45
10. Watford                  42  10  6  5  35  23   7  4 10  22  31   44
11. Queen's Park Rangers     42  10  4  7  34  24   6  6  9  20  25   42
12. Charlton Athletic        42  11  6  4  33  14   3  8 10  22  37   42
13. Bristol Rovers           42   7  9  5  25  19   6  7  8  10  17   42
14. Brentford                42   9  4  8  27  23   4  8  9  14  28   38
15. Southend United          42  10  6  5  35  18   2  7 12  14  36   37
16. Gillingham               42  13  4  4  38  18   2  3 16  13  41   37
17. Merthyr Town             42  10  4  7  27  17   1 10 10  12  31   36
18. Norwich City             42   8  7  6  29  26   5  3 13  22  45   36
19. Reading                  42   9  8  4  24  15   1  6 14  12  40   34
20. Exeter City              42  10  4  7  27  18   3  3 15  20  66   33

这是非常规则的,但是没有标准的分隔符,并且列宽不是表到表的标准(即使在相同的文件中)。 (仅空格不是足够的分隔符,因为许多名称包含空格,在某些地方,列仅由一个空格分隔。)

我想将它解析为Python对象,但目前还不清楚最好的方法是什么。有没有办法使用CSV模块解析它?我需要使用正则表达式吗?有人写了一个很棒的python库来解析表格文本文件吗?

3 个答案:

答案 0 :(得分:1)

制作正则表达式。 Look it up here for explanation/modifying.

使用[\D]+?提取行的名称(如Accrington)。这意味着“尽可能多地使用非数字来填充线条”。 (+? - 非贪心)所以你可以得到字母和(最小)空格,这就是你的行的名字......

import re
pattern = re.compile(r"^(\d+.)\s*([\D]+?)" + r"\s+(\d+)"*12 + r"\s*$")

<强>测试

match = pattern.match("7. Accrington               22   5  3  3  26  17   1  5  5  22  31   20")
print match.groups()
Out[133]: 
('7.',
 'Accrington',
 '22',
 '5',
 '3',
 '3',
 '26',
 '17',
 '1',
 '5',
 '5',
 '22',
 '31',
 '20')

match2 = pattern.match("91. Accrington Bay              22   5  3  3  26  17   1  5  5  22  31   20")
print match2
Out[134]: 
('91.',
 'Accrington Bay',
 '22',
 '5',
 '3',
 '3',
 '26',
 '17',
 '1',
 '5',
 '5',
 '22',
 '31',
 '20')

答案 1 :(得分:0)

最简单的解决方案是使用正则表达式。

您可以使用split()方法(Python包含的re模块除外)在每个连续空格序列中拆分数据。

import re

data = '7. Accrington               22   5  3  3  26  17   1  5  5  22  31   20'
for line in re.split('\n+', data):
    print(re.split('\s+', line))

将打印以下内容:

['7.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '20']

请注意,上面的示例还处理多行数据(假设这些行由连续的换行符分隔)。

答案 2 :(得分:0)

skipinitialspace是您使用csv模块所需的内容。

$ cat << EOF > /tmp/sample.csv
> 7. Accrington               22   5  3  3  26  17   1  5  5  22  31   20
> 7. Accrington               22   5  3  3  26  17   1  5  5  22  31   20
> 8. Accrington               22   5  3  3  26  17   1  5  5  22  31   22
> 7. Accrington               22   5  3  3  26  17   1  5  5  22  31   21
> EOF
$ python
Python 2.7.5 (default, Aug 25 2013, 00:04:04) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import csv
>>> reader = csv.reader(open('/tmp/sample.csv'), skipinitialspace=True, quoting=csv.QUOTE_NONE, delimiter=' ')
>>> for row in reader: 
...     print row
... 
['7.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '20']
['7.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '20']
['8.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '22']
['7.', 'Accrington', '22', '5', '3', '3', '26', '17', '1', '5', '5', '22', '31', '21']

不要忘记你可以解压缩每行的结果,如下所示:

>>> for pk, name, a, b, c, d, e, f, g, h, i, j, k, l in reader: