Python 清洗、提取 txt 内数据的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
DannyVim
V2EX    问与答

Python 清洗、提取 txt 内数据的问题

  •  
  •   DannyVim 2017-12-30 11:37:20 +08:00 3229 次点击
    这是一个创建于 2897 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现有 sample.txt 内文件内容如下:

    一级学科代码及名称:0101 哲学 本一级学科中,全国具有“博士授权”的高校共 48 所,本次参评 38 所;部分具有“硕士授权”的高校也参加了评估;参评高校共计 84 所(注:评估结果相同的高校排序不分先后,按学校代码排列)。 评估结果 学校代码及名称 A+ 10001 北京大学 10246 复旦大学 A 10002 中国人民大学 10284 南京大学 A- 10027 北京师范大学 10183 吉林大学 10486 武汉大学 10558 中山大学 B+ 10003 清华大学 10055 南开大学 10212 黑龙江大学 10269 华东师范大学 10286 东南大学 10335 浙江大学 10422 山东大学 10487 华中科技大学 B 10052 中央民族大学 10108 山西大学 10145 东北大学 10247 同济大学 10319 南京师范大学 10384 厦门大学 10542 湖南师范大学 10610 四川大学 10718 陕西师范大学 B- 10140 辽宁大学 10141 大连理工大学 10270 上海师范大学 10285 苏州大学 10533 中南大学 10574 华南师范大学 10635 西南大学 10698 西安交通大学 C+ 10053 中国政法大学 10075 河北大学 10357 安徽大学 10385 华侨大学 10403 南昌大学 10475 河南大学 10512 湖北大学 10520 中南财经政法大学 10730 兰州大学 C 10203 吉林师范大学 10280 上海大学 10531 吉首大学 10590 深圳大学 10656 西南民族大学 10673 云南大学 评估结果 学校代码及名称 C 10674 昆明理工大学 10726 西北政法大学 C- 10094 河北师范大学 10166 沈阳师范大学 10370 安徽师范大学 10476 河南师范大学 10593 广西大学 10636 四川师范大学 10652 西南政法大学 10681 云南师范大学 

    希望能够把结果输出为形如如下的结构(最后打算输出 csv 格式的数据):

    header = [学校,A+,A,A-,B+,B,B-,C+,C,C-] row= [(北京大学,哲学,,,,,,,,) (云南师范大学,,,,,,,,哲学)] 

    还是 python 的新手,想了很久不知道该怎么处理。求诸位 V2EXer 可以指点一下思路。

    16 条回复    2017-12-30 23:02:15 +08:00
    u1ucky
        1
    u1ucky  
       2017-12-30 11:48:13 +08:00
    可以用 enumerate 逐行遍历,处理结果放到两个数组里。
    czb
        2
    czb  
       2017-12-30 11:52:46 +08:00 via Android
    With open .. as file
    For line in file
    Regex
    Universe
        3
    Universe  
       2017-12-30 13:54:39 +08:00   1
    ```
    {
    "学校名称": [[A+学科名称列表],[A 学科名称列表]...],
    "学校名称": [[A+学科名称列表],[A 学科名称列表]]...
    }
    ```
    DannyVim
        4
    DannyVim  
    OP
       2017-12-30 14:24:29 +08:00
    @czb 我的问题就在怎么把数据正确地读出来。可以更细节一下吗?
    DannyVim
        5
    DannyVim  
    OP
       2017-12-30 14:24:48 +08:00
    @Universe 其实我的问题在于怎么读取数据
    DannVim
        6
    DannyVim  
    OP
       2017-12-30 14:25:05 +08:00
    @aimkiray 可以更细节一些吗?
    yangyaofei
        7
    yangyaofei  
       2017-12-30 16:01:27 +08:00 via Android
    你需要正则表达式
    anguslg
        8
    anguslg  
       2017-12-30 16:14:30 +08:00
    这种数据也要事先人工清洗一遍成代码易读的才行, 然后用 pandas 会方便很多
    SakuraSa
        9
    SakuraSa  
       2017-12-30 17:07:29 +08:00
    虽然出来的数据格式不太对,但是应该很好转换过去了
    https://gist.github.com/anonymous/c5c24ec12ee98f55030c7c70680a8911
    jpmorn
        10
    jpmorn  
       2017-12-30 17:09:50 +08:00
    awesome-wechat-jump :)
    SakuraSa
        11
    SakuraSa  
       2017-12-30 17:25:43 +08:00
    上面的那个 gist 被我不小心删掉了,换一个
    SakuraSa
        12
    SakuraSa  
       2017-12-30 17:25:49 +08:00   1
    omph
        13
    omph  
       2017-12-30 18:10:21 +08:00
    鉴于数据比较整洁,分析过程可以用流式分析法:
    1. 记录分割:先把文本按字符串“一级学科代码及名称:”分割( split ),得到不同学科的数据。每段再按空白分割。
    2. 分析和归类:遇到“ A+”等,记录,遇到以“大学”结尾,存储。数据结构用 3 楼的思路
    3. 整理数据为最终格式
    5mins
        14
    5mins  
       2017-12-30 18:24:02 +08:00   2
    如果不嫌弃正则慢,可以用正则,但正则是最烦人的,因为各个版本各种语言都有差别。

    楼上 SakuraSa 的代码已经不错了,但看了下正则写得有点问题,会导致丢失数据。

    可以试下替换成这两条:

    ```python
    ([A-E][+|-]?)[^A-E]*
    ([0-9]{5}) *([\u4e00-\u9fa5]+)[^0-9]
    ```

    只在在线的正则表达式的网站测试过。

    ![正则 1]( "正则 1")

    ![正则 2]( "正则 2")
    DannyVim
        15
    DannyVim  
    OP
       2017-12-30 22:57:44 +08:00
    @5mins 正则是比较慢的一种方式的话,那什么工具在速度上会比较快呢?因为总的文档其实有三万行的样子,这个只是其中一部分。
    SakuraSa
        16
    SakuraSa  
       2017-12-30 23:02:15 +08:00
    @DannyVim #15
    30k line 对于现在的电脑来说不算大文件吧
    我觉得直接用上面的代码 10s 都用不了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1165 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 17:40 PVG 01:40 LAX 09:40 JFK 12:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86