Neo4j & Python 構(gòu)建中國行政區(qū)劃圖

哇標(biāo)題看起來挺厲害的,其實沒有很難啦挖胃,而且非常有趣。

我為什么要做這個

我本人就很討厭看到這種標(biāo)題——我為什么xxx梆惯?喵喵喵冠骄?你為什么xxx關(guān)我什么事?唉加袋,人總是會變成自己討厭的人嘛。

換個說法抱既,說說做這個的初衷职烧,其實沒有什么初衷,被逼的防泵。

為了盡早完成畢業(yè)設(shè)計可以出去打工蚀之,我選擇提前聯(lián)系導(dǎo)師。于是就被提供了兩個題目捷泞,我決定做水利相關(guān)的知識圖譜足删。你看,多么河海特色锁右!水水水失受,離開水就不能活了讶泰,沒毛病。

于是先從圖數(shù)據(jù)庫入手拂到,neo4j是個好東西痪署,就決定是你了。在構(gòu)建復(fù)雜的水水水相關(guān)實體前兄旬,我先拿中國行政區(qū)劃數(shù)據(jù)試個水狼犯,邏輯相對簡單,就一種隸屬關(guān)系领铐。

獻(xiàn)上美圖:

Screen Shot 2017-11-10 at 16.08.23.png

起步

首先悯森,準(zhǔn)備一下原料,中國行政區(qū)劃元數(shù)據(jù)绪撵,不求完全結(jié)構(gòu)化瓢姻,起碼半結(jié)構(gòu)化,不然會很痛苦莲兢,畢竟有70W+數(shù)據(jù)汹来。

Neo4j一套,python或者什么腳本語言一款改艇,腦子一坨收班,足夠了。

首先我拿到70W+的XML文件谒兄,哎喲我去摔桦,ls一下都卡半天,我都害怕python會不會應(yīng)付不來承疲,跑一遍幾小時可能就太慘了邻耕。

首先用python列出幾個文件:

files = os.listdir(datas_path)
print(files[0])

哈哈哈,我先搞個文件名燕鸽,然后直接打開這個文件兄世,避免了「我不能ls就不知道文件名,不知道文件名就不能看內(nèi)容」的問題啊研∩髟可以看到里面的大致結(jié)構(gòu)恍飘,這里取一部分:

<mdExtInfo>     
    <obj_att>      
        <AD_GRAD>        
            <key>行政區(qū)劃級別</key>        
            <value>村</value>      
        </AD_GRAD>      
        <AD_CODE>        
            <key>行政區(qū)劃代碼</key>        
            <value>441323121207</value>      
        </AD_CODE>      
        <UP_AD_NAME>        
            <key>上級行政區(qū)劃名稱</key>        
            <value>白盆珠鎮(zhèn)</value>      
        </UP_AD_NAME>      
        <AD_FULL_NAME>        
            <key>行政區(qū)劃全稱</key>        
            <value>廣東省-惠州市-惠東縣-白盆珠鎮(zhèn)-布心村民委員會</value>      
        </AD_FULL_NAME>      
        <AD_NAME>        
            <key>行政區(qū)劃名稱</key>        
            <value>布心村民委員會</value>      
        </AD_NAME>    
    </obj_att>   
</mdExtInfo> 

枚舉行政區(qū)劃級別

唉额湘,幾十萬文件营勤,我都不知道有幾種行政區(qū),先跑一遍看看有哪些區(qū)劃級別沟娱。

核心代碼:

cates = set()
for file in files:
    doc = parse(datas_path + file)
    for item in doc.iterfind('mdExtInfo/obj_att/AD_GRAD'):
        title = item.findtext('value')
        cates.add(title)
        print(title, file, cates)

大概不到十分鐘就能跑完氛驮,最后得到一共有6種級別:縣級、村济似、國家級矫废、鄉(xiāng)級盏缤、地市級、省級磷脯。

給這些文件分類

每次都跑十分鐘太過分了蛾找,而且我發(fā)現(xiàn),不同的級別赵誓,XML里的結(jié)構(gòu)不同打毛,比如省級有十幾個字段,鄉(xiāng)級只有五個俩功。所以分類是必須的幻枉。

按照不同級別,將同級別的文件名放在一個文件里诡蜓,方便以后遍歷熬甫。

到這里,我突然明白了一些道理蔓罚,來來來椿肩,給自己加點(diǎn)戲!

本來以為都是非結(jié)構(gòu)化數(shù)據(jù)豺谈,剛好有在看機(jī)器學(xué)習(xí)郑象,哇可以學(xué)以致用了,把數(shù)據(jù)扔進(jìn)去茬末,自動聚類厂榛,開心的當(dāng)上調(diào)參男孩…… 然而我發(fā)現(xiàn)數(shù)據(jù)格式化的挺不錯,就開始自己去找他們的特征丽惭,這特喵不就是——人肉學(xué)習(xí)嘛击奶!然而再反過來想,機(jī)器學(xué)習(xí)到底是什么呢责掏?

構(gòu)造 Neo4j 需要的 CSV

抽取屬性

這么一大坨數(shù)據(jù)要導(dǎo)入的柜砾,用CQL實在太慢,生成指定格式的CSV文件就OK啦~真簡單~

AD_CODE,AD_NAME,AD_GRAD,AD_AREA,AD_FULL_NAME,AD_ABBR_NAME,LOW_LEFT_LONG,UP_RIGHT_LONG,UP_RIGHT_LAT,AD_STAT_LAT,AD_STAT,LOW_LEFT_LAT,AD_STAT_LONG
610000000000,陜西省,省級,197025.84,陜西省,陜西,105.4872,111.2422,39.58533,34.26645358,西安市新城區(qū)新城大院,31.70674,108.94952476
650000000000,新疆維吾爾自治區(qū),省級,1660000,新疆維吾爾自治區(qū),新疆,73.49989,96.38728,49.18006,43.79179105,烏魯木齊市中山路479號,34.33374,87.62484437
130000000000,河北省,省級,187700,河北省,河北,113.4551,119.8485,42.61558,38.03705206,石家莊市長安區(qū)裕華東路113號,36.04881,114.52429283

...

哈哈哈哈换衬,先把它們有用的屬性都拿出來局义,按級別分類放到6個CSV文件中,結(jié)構(gòu)如上冗疮,從此就可以舒服很多了,畢竟不用遍歷幾十萬個文件了檩帐。

構(gòu)建行政單位實體

等…… 等一下……

其實在這之前术幔,我發(fā)現(xiàn)了很多坑爹的地方,比如地市級單位有14個屬性湃密,但有個別數(shù)據(jù)只有幾個屬性诅挑,所以遍歷的時候一定要判斷四敞,不存在的話要用空字符串替代,不然CSV對不齊后面就會更坑拔妥。

首先做個屬性映射忿危,我不想存到數(shù)據(jù)庫里字段都是瞎眼的大寫:

prop_maps = {
    'AD_CODE': 'code:ID(AD)',
    'AD_NAME': 'name',
    # 'AD_GRAD': 'level',
    'AD_AREA': 'area:double',
    'AD_FULL_NAME': 'full_name',
    'AD_ABBR_NAME': 'abbr_name',
    'LOW_LEFT_LONG': 'low_left_longtitude:double',
    'UP_RIGHT_LONG': 'up_right_longtitude:double',
    'UP_RIGHT_LAT': 'up_right_latitude:double',
    'AD_STAT_LAT': 'station_latitude:double',
    'AD_STAT': 'station',
    'LOW_LEFT_LAT': 'low_left_latitude:double',
    'AD_STAT_LONG': 'station_longtitude:double'
    # 'UP_AD_NAME': 'father_name'
}

根據(jù) Neo4j Import Tool 上的格式,我們要注意ID字段没龙,以及LABEL字段铺厨,我決定給它們兩個標(biāo)簽,一個是級別硬纤,比如Province解滓,一個是AD,表示Administrative Division 行政區(qū)劃筝家,畢竟這個數(shù)據(jù)庫還會有很多水水水的數(shù)據(jù)進(jìn)來洼裤。

code:ID(AD),name,area:double,full_name,abbr_name,low_left_longtitude:double,up_right_longtitude:double,up_right_latitude:double,station_latitude:double,station,low_left_latitude:double,station_longtitude:double,:LABEL
610000000000,陜西省,197025.84,陜西省,陜西,105.4872,111.2422,39.58533,34.26645358,西安市新城區(qū)新城大院,31.70674,108.94952476,AD;Province
650000000000,新疆維吾爾自治區(qū),1660000,新疆維吾爾自治區(qū),新疆,73.49989,96.38728,49.18006,43.79179105,烏魯木齊市中山路479號,34.33374,87.62484437,AD;Province
130000000000,河北省,187700,河北省,河北,113.4551,119.8485,42.61558,38.03705206,石家莊市長安區(qū)裕華東路113號,36.04881,114.52429283,AD;Province

...

最后的數(shù)據(jù)如上所示(省級部分)。直接看一坨CSV體驗很差對吧溪王,其實不用看全腮鞍,看到主要的幾個字段就是可以了,比如code:ID(AD)莹菱,表示code字段移国,行政代碼,ID表示我要用于之后導(dǎo)入關(guān)系的主鍵芒珠,(AD)表示這個ID不是全局的桥狡,是一個叫AD的group,可以理解命名空間皱卓,詳情請看官方文檔裹芝。還有LABEL字段,表示標(biāo)簽……廢話…… area:double表示用雙精度娜汁,否則默認(rèn)為字符串嫂易,你不希望數(shù)字都變成字符串吧。

構(gòu)建行政區(qū)上下級關(guān)系

在這之前掐禁,必須要驗證很多細(xì)節(jié)怜械,比如真的所有數(shù)據(jù)都有上級這個屬性嘛?所有數(shù)據(jù)都是完美的符合規(guī)則的嘛傅事?果然不是缕允。。蹭越。

甚至障本,數(shù)據(jù)還有一些錯誤的,比如有一條就是陜西省-嘉峪關(guān)市-市轄區(qū),為什么我發(fā)現(xiàn)他是錯誤的呢驾霜?我是陜西人嘛案训?我地理及格了嘛?NONONO粪糙!因為我想驗證一下所有地名的全稱强霎,去掉最后一段,即上級行政區(qū)全稱蓉冈,是否存在城舞。哈哈哈不存在的,結(jié)果就是沒找到甘肅省-嘉峪關(guān)市-市轄區(qū)這條數(shù)據(jù)洒擦,仿佛鏈條都斷掉了椿争。

于是我跑了一下元數(shù)據(jù),看看嘉峪關(guān)市到底是哪里的熟嫩,發(fā)現(xiàn)陜西和甘肅都有秦踪,見鬼了,去網(wǎng)上搜了一下掸茅,不存在的椅邓。要把這條數(shù)據(jù)的「陜西」替換為「甘肅」,不想動元數(shù)據(jù)昧狮,所以寫在了清理數(shù)據(jù)的腳本中景馁。

用 UP_AD_NAME 字段找上級

用幾個字典,存下地名和代號逗鸣,然后拿 UP_AD_NAME 去匹配上一級的字典合住。

我太天真了哈哈哈,測試一下有多少重名的撒璧,果然到了縣級就沒法看了透葛,什么「西城區(qū)」,哪個城市都有卿樱。

所以干脆拿全名前綴來匹配

直接把所有行政區(qū)存到一個字典僚害,全名為鍵,代號為值繁调。找一個行政區(qū)的上級時萨蚕,其實就是去掉最后一段。比如 江蘇省-南京市-江寧區(qū) 的上級就是 江蘇省-南京市蹄胰,我驗證了一下是不是字典里都存在岳遥。果然又?叒叕有幾個不聽話的數(shù)據(jù)。

比如 新疆生產(chǎn)建設(shè)兵團(tuán)-農(nóng)四師-兵團(tuán)七十六團(tuán)--三連 最后居然兩個-裕寨,中間是空的寒随,我發(fā)現(xiàn)有這樣的 新疆生產(chǎn)建設(shè)兵團(tuán)-農(nóng)四師-兵團(tuán)七十六團(tuán)-兵團(tuán)七十六團(tuán) 數(shù)據(jù),就嘗試給他們都加上,但結(jié)果是有些又找不到了妻往。所以我干脆刪了,后果是某些村級直接屬于縣級试和,算了算了沒毛病讯泣,畢竟數(shù)據(jù)沒給全,至少這樣沒什么大問題阅悍。

最后好渠!居然發(fā)現(xiàn)有相同全名的,無話可說节视,仔細(xì)觀察可以發(fā)現(xiàn)拳锚,都是村級的,名字一樣寻行,代號卻不同霍掺,只能認(rèn)為是干擾數(shù)據(jù),隨緣選一個吧拌蜘。

完成CSV

:START_ID(AD),:END_ID(AD),:TYPE
610000000000,000000000000,BELONGS_TO
650000000000,000000000000,BELONGS_TO
130000000000,000000000000,BELONGS_TO
660000000000,000000000000,BELONGS_TO
140000000000,000000000000,BELONGS_TO
520000000000,000000000000,BELONGS_TO
360000000000,000000000000,BELONGS_TO
630000000000,000000000000,BELONGS_TO
230000000000,000000000000,BELONGS_TO

...

最后就是生成這樣的數(shù)據(jù)杆烁,再寫個導(dǎo)入 neo4j 的腳本即可。

怎么玩 Neo4j

算了下一篇文章再寫吧简卧,累死了……

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末兔魂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子举娩,更是在濱河造成了極大的恐慌析校,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铜涉,死亡現(xiàn)場離奇詭異智玻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)骄噪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門尚困,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人链蕊,你說我怎么就攤上這事事甜。” “怎么了滔韵?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵逻谦,是天一觀的道長。 經(jīng)常有香客問我陪蜻,道長邦马,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮滋将,結(jié)果婚禮上邻悬,老公的妹妹穿的比我還像新娘。我一直安慰自己随闽,他們只是感情好父丰,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掘宪,像睡著了一般蛾扇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上魏滚,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天镀首,我揣著相機(jī)與錄音,去河邊找鬼鼠次。 笑死更哄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的须眷。 我是一名探鬼主播竖瘾,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼花颗!你這毒婦竟也來了捕传?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤扩劝,失蹤者是張志新(化名)和其女友劉穎庸论,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棒呛,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡聂示,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了簇秒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鱼喉。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖趋观,靈堂內(nèi)的尸體忽然破棺而出扛禽,到底是詐尸還是另有隱情,我是刑警寧澤皱坛,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布编曼,位于F島的核電站,受9級特大地震影響剩辟,放射性物質(zhì)發(fā)生泄漏掐场。R本人自食惡果不足惜往扔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望熊户。 院中可真熱鬧萍膛,春花似錦、人聲如沸嚷堡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽麦到。三九已至,卻和暖如春欠肾,著一層夾襖步出監(jiān)牢的瞬間瓶颠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工刺桃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留粹淋,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓瑟慈,卻偏偏與公主長得像桃移,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子葛碧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容