我正在尝试读取和解析人口普查局的美国社区调查公共使用微样本数据发布的数据字典,如此处所示。
它的格式相当好,尽管在插入一些解释性说明的地方有一些失误。
我认为我的首选结果是获取每个变量一行的数据框,并将给定变量的所有值标签序列化到一个字典中,该字典存储在同一行的值字典字段中(尽管不会采用分层 json 格式不好,但更复杂。
我得到以下代码:
import pandas as pd
import re
import urllib2
data = urllib2.urlopen('http://www.census.gov/acs/www/Downloads/data_documentation/pums/DataDict/PUMSDataDict13.txt')
## replace newline characters so we can use dots and find everything until a double
## carriage return (replaced to ||) with a lookahead assertion.
data=data.replace('\n','|')
datadict=pd.DataFrame(re.findall("([A-Z]{2,8})\s{2,9}([0-9]{1})\s{2,6}\|\s{2,4}([A-Za-z\-\(\) ]{3,85})",data,re.MULTILINE),columns=['variable','width','description'])
datadict.head(5)
+----+----------+-------+------------------------------------------------+
| | variable | width | description |
+----+----------+-------+------------------------------------------------+
| 0 | RT | 1 | Record Type |
+----+----------+-------+------------------------------------------------+
| 1 | SERIALNO | 7 | Housing unit |
+----+----------+-------+------------------------------------------------+
| 2 | DIVISION | 1 | Division code |
+----+----------+-------+------------------------------------------------+
| 3 | PUMA | 5 | Public use microdata area code (PUMA) based on |
+----+----------+-------+------------------------------------------------+
| 4 | REGION | 1 | Region code |
+----+----------+-------+------------------------------------------------+
| 5 | ST | 2 | State Code |
+----+----------+-------+------------------------------------------------+
到目前为止,一切都很好。变量列表以及每个变量的字符宽度都在那里。
我可以扩展它并获得额外的行(值标签所在的位置),如下所示:
datadict_exp=pd.DataFrame(
re.findall("([A-Z]{2,9})\s{2,9}([0-9]{1})\s{2,6}\|\s{4}([A-Za-z\-\(\)\;\<\> 0-9]{2,85})\|\s{11,15}([a-z0-9]{0,2})[ ]\.([A-Za-z/\-\(\) ]{2,120})",
data,re.MULTILINE))
datadict_exp.head(5)
+----+----------+-------+---------------------------------------------------+---------+--------------+
| id | variable | width | description | value_1 | label_1 |
+----+----------+-------+---------------------------------------------------+---------+--------------+
| 0 | DIVISION | 1 | Division code | 0 | Puerto Rico |
+----+----------+-------+---------------------------------------------------+---------+--------------+
| 1 | REGION | 1 | Region code | 1 | Northeast |
+----+----------+-------+---------------------------------------------------+---------+--------------+
| 2 | ST | 2 | State Code | 1 | Alabama/AL |
+----+----------+-------+---------------------------------------------------+---------+--------------+
| 3 | NP | 2 | Number of person records following this housin... | 0 | Vacant unit |
+----+----------+-------+---------------------------------------------------+---------+--------------+
| 4 | TYPE | 1 | Type of unit | 1 | Housing unit |
+----+----------+-------+---------------------------------------------------+---------+--------------+
这样就得到了第一个值和相关的标签。我的正则表达式问题是如何从头到尾重复多行匹配\s{11,15}
——即一些变量有大量的唯一值(ST
或者state code
后面跟着大约 50 行,表示每个状态的值和标签)。
我很早就用管道在源文件中的回车上进行了更改,以为我可以无耻地依靠点来匹配所有内容,直到双回车,指示该特定变量的结束,这就是我卡住的地方。
那么——如何将多行模式重复任意次数。
(后面的复杂情况是字典中没有完全列举一些变量,但显示了有效的值范围。NP
例如[与同一家庭相关的人数],用 `02..20` 表示描述。如果我不考虑这一点,我的解析当然会错过这些条目。)