用遞歸計(jì)算股權(quán)層級(jí)

一、問題背景:

一個(gè)集團(tuán)公司下設(shè)有多層企業(yè)镜盯,整體的股權(quán)結(jié)構(gòu)呈垂直特征,即A公司控制B公司猖败、B公司控制C公司速缆,依次向下,現(xiàn)在想獲取每個(gè)公司在這個(gè)垂直結(jié)構(gòu)中的股權(quán)層級(jí)辙浑,如果是頂層的A公司激涤,就是1級(jí),層級(jí)越低判呕,級(jí)數(shù)越大倦踢,這里約定:假如一個(gè)公司G即被母公司A直接持股,也被A公司的子公司B公司直接持股侠草,則G的層級(jí)取2辱挥,而非3。案例測(cè)試數(shù)據(jù)為:


一個(gè)簡單的股權(quán)結(jié)構(gòu)

形象的說边涕,就是對(duì)于每個(gè)子公司晤碘,找到最短的“回A之路”。你可以先不看下面的代碼功蜓,想一想應(yīng)該怎么解決這個(gè)問題园爷。

二、代碼實(shí)現(xiàn)如下:

a=Ctrsht['子公司'].unique().tolist()#數(shù)組a記錄了去除所有的非重復(fù)機(jī)構(gòu)
b=[]#數(shù)組b用于記錄每個(gè)機(jī)構(gòu)的層級(jí)
def levelsearch(level,name):
    if name=='A':#遞歸函數(shù)必須由明確的退出機(jī)制式撼,否則就是死循環(huán)
        return(level,name)#當(dāng)傳入的機(jī)構(gòu)名稱為A時(shí)童社,表示子公司順著股權(quán)路徑找到了A公司,這時(shí)level就是返回的級(jí)數(shù)
    else:#如果尚未返回A公司著隆,則記錄此時(shí)尋找到的母公司是哪一個(gè)
        for i in range(len(Ctrsht['子公司'])):#遍歷上面的dataframe
            if Ctrsht.iloc[i,1]==name:#定位當(dāng)前傳入的機(jī)構(gòu)名稱的所在行
                if Ctrsht.iloc[i,0]=='A':#如果該行的母公司即為A則返回層數(shù)
                    return(level+1,'A')
                else:
                    return(levelsearch(level+1,Ctrsht.iloc[i,0]))#如果該行的母公司不是A扰楼,則調(diào)用函數(shù)本身,下一次傳入的機(jī)構(gòu)名稱即該行的母公司
            else:
                pass
for i in range(len(a)):#遍歷子公司數(shù)組美浦,計(jì)算每個(gè)子公司的層級(jí)
    b.append(levelsearch(1,a[i])[0])
equitylevel=pd.DataFrame(a)
equitylevel['股權(quán)層級(jí)']=b
equitylevel
股權(quán)層級(jí)

三弦赖、改進(jìn):

上述程序有個(gè)問題:有的子公司出現(xiàn)了多次,比如F公司浦辨,程序返回層級(jí)為F第一次出現(xiàn)時(shí)的股權(quán)層級(jí)蹬竖,即為3(A--B--F),而如果源數(shù)據(jù)文件中將第6行E->F放在B->F前面,則程序返回的F層級(jí)就是6(A--B--C--D--E--F)案腺。
因此當(dāng)前的結(jié)果依賴于股權(quán)結(jié)構(gòu)表的排序庆冕,需要進(jìn)一步完善。

完善步驟為:
1劈榨、找到某公司在“子公司”列中出現(xiàn)的所有行數(shù)(F公司就是第5行和第6行)
2、分別計(jì)算該公司在各行時(shí)返回的股權(quán)層級(jí)(F公司就是3和4)
3晦嵌、根據(jù)問題的初始規(guī)定原則同辣,取過程2中的最小值

這里有個(gè)一非常繞的情境,就是F的母公司E惭载,在各行也出現(xiàn)了兩次旱函,兩種回A的路徑分別是ABCDE和ABCE,這樣返回的F股權(quán)層級(jí)就是6和5描滔,按照規(guī)定原則棒妨,結(jié)果應(yīng)該是5(即選擇ABCE路徑),所以在遞歸函數(shù)的定義中含长,必須用循環(huán)將最佳回A路徑找出券腔。

首先定義遞歸函數(shù)

#2020/3/7改進(jìn)
#3/7改進(jìn)2
def levelsearch(level,position,name):#level為初始層級(jí),一般為1拘泞,position為子公司所在行數(shù)
    if name=='A':#name記錄當(dāng)前子公司的母公司纷纫,如果為A則跳出遞歸程序
        return(level,position,name)
    else:
        if Ctrsht.iloc[position,1]==name:
            if Ctrsht.iloc[position,0]=='A':#如果當(dāng)前子公司的母公司為A,則層級(jí)加1陪腌,遞歸結(jié)束
                return(level+1,position,'A')
            else:#如果當(dāng)前子公司的母公司不為A辱魁,先記錄母公司在“子公司”列出現(xiàn)的行數(shù),然后調(diào)用程序自身
                temPosition=[]
                for i in range(len(Ctrsht['子公司'])):
                    if Ctrsht.iloc[i,1]==Ctrsht.iloc[position,0]:
                        temPosition.append(i)#母公司在“子公司”列出現(xiàn)的行數(shù)可能為多個(gè)诗鸭,必須用數(shù)組記錄染簇,并遍歷數(shù)組調(diào)用遞歸函數(shù)
                templevel={}#用字典記錄母公司每次返回的股權(quán)層級(jí)
                levelsig=0
                for k in temPosition:
                    templevel[k]=levelsearch(levelsig,k,Ctrsht.iloc[k,1])[0]
                minilevel = min(templevel, key=lambda x:templevel[x])
                return(levelsearch(level+1,minilevel,Ctrsht.iloc[minilevel,1]))
        else:
            pass

然后對(duì)每個(gè)子公司分別計(jì)算出現(xiàn)的行數(shù),并調(diào)用遞歸函數(shù)計(jì)算min{基于各行數(shù)計(jì)算的股權(quán)層級(jí)}

a=Ctrsht['子公司'].unique().tolist()#去除所有的非重復(fù)機(jī)構(gòu)
b=[]#記錄每個(gè)機(jī)構(gòu)的層級(jí)
for i in range(len(a)):
    linenum=[]#獲得每個(gè)機(jī)構(gòu)在持股機(jī)構(gòu)列中出現(xiàn)的行數(shù)
    for k in range(len(Ctrsht['子公司'])):
        if Ctrsht.iloc[k,1]==a[i]:
            linenum.append(k)
    agencylevel=[]#記錄不同出現(xiàn)行數(shù)計(jì)算的股權(quán)層級(jí)
    for j in linenum:
        agencylevel.append(levelsearch(1,j,a[i])[0])
    b.append(min(agencylevel))
equitylevel=pd.DataFrame(a)
equitylevel['改進(jìn)的股權(quán)層級(jí)']=b
equitylevel
image.png

可以看到E的股權(quán)層級(jí)得到了修正强岸。
下面這個(gè)圖可以看到锻弓,F(xiàn)的層級(jí)是在比較3和5之后,選擇的最小值请唱,E的層級(jí)是在比較4和5之后弥咪,選擇的最小值


E

F

結(jié)語:遞歸是目前我寫過最難的程序了,對(duì)邏輯的要求高十绑,中間的各種計(jì)數(shù)變量聚至、臨時(shí)變量也多,大腦要清醒本橙,但遞歸代碼的簡潔和高效也使遞歸成為應(yīng)用非常廣泛的算法
算是剛?cè)肓碎T扳躬,以后再修煉吧~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子贷币,更是在濱河造成了極大的恐慌击胜,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件役纹,死亡現(xiàn)場(chǎng)離奇詭異偶摔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)促脉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門辰斋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瘸味,你說我怎么就攤上這事宫仗。” “怎么了旁仿?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵藕夫,是天一觀的道長。 經(jīng)常有香客問我枯冈,道長毅贮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任霜幼,我火速辦了婚禮嫩码,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘罪既。我一直安慰自己铸题,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布琢感。 她就那樣靜靜地躺著丢间,像睡著了一般。 火紅的嫁衣襯著肌膚如雪驹针。 梳的紋絲不亂的頭發(fā)上烘挫,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音柬甥,去河邊找鬼饮六。 笑死,一個(gè)胖子當(dāng)著我的面吹牛苛蒲,可吹牛的內(nèi)容都是我干的卤橄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼臂外,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼窟扑!你這毒婦竟也來了喇颁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤嚎货,失蹤者是張志新(化名)和其女友劉穎橘霎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體殖属,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姐叁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了忱辅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片七蜘。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖墙懂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扮念,我是刑警寧澤损搬,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站柜与,受9級(jí)特大地震影響巧勤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜弄匕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一颅悉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迁匠,春花似錦剩瓶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亡哄,卻和暖如春枝缔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蚊惯。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國打工愿卸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人截型。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓趴荸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親菠劝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赊舶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

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

  • 選擇題部分 1.()部門負(fù)責(zé)日常監(jiān)督檢查工作,安全巡視的同時(shí)進(jìn)行消防檢查,推動(dòng)消防安全制度的貫徹落實(shí)睁搭。 A: 消防...
    skystarwuwei閱讀 15,205評(píng)論 0 3
  • 高級(jí)鉗工應(yīng)知鑒定題庫(858題) ***單選題*** 1. 000003難易程度:較難知識(shí)范圍:相關(guān)4 01答案:...
    開源時(shí)代閱讀 5,780評(píng)論 1 9
  • 選擇題部分 1.(),只有在發(fā)生短路事故時(shí)或者在負(fù)荷電流較大時(shí),變流器中才會(huì)有足夠的二次電流作為繼電保護(hù)跳閘之用。...
    skystarwuwei閱讀 12,917評(píng)論 0 7
  • 說到影子笼平,我想到了去年張藝謀拍的電影《影》园骆,講述的是一個(gè)關(guān)于替身也就是影子的故事。電影中影子如同與真身互為一體寓调,令...
    燕敏Lisa閱讀 99評(píng)論 0 0
  • 影響他人最重要的條件是什么夺英? 1.正能量晌涕,積極主動(dòng) 2.利他 3.互賴 4. 領(lǐng)導(dǎo)力,牽引力 5.內(nèi)心堅(jiān)...
    森塬閱讀 489評(píng)論 0 1