In [1]:
from graphviz import Digraph
from math import isnan
In [2]:
import pandas
In [3]:
def get_info(url):
原始資料 = pandas.read_html(url, encoding="utf8")[1]
學程 = 原始資料[原始資料[2].notnull()]
學程=學程.set_index(學程[0]).drop(0, 1)
學程.columns = 學程.iloc[0]
學程 = 學程[1:]
學程['學分']=學程['學分'].astype(float)
return 學程
In [4]:
# 104 學年度應數基礎學程
url = 'http://sys.ndhu.edu.tw/aa/class/RuleSearch/RuleDetail.aspx?id=104,1040000003,B,AM___1042971'
基礎 = get_info(url)
# 印出結果,其他學程省略
基礎
Out[4]:
In [5]:
# 104 學年度數學科學組核心(一)學程
url = 'http://sys.ndhu.edu.tw/aa/class/RuleSearch/RuleDetail.aspx?id=104,1040000007,B,AM___1042971'
數科組核心一 = get_info(url)
In [6]:
# 104 學年度數學科學組核心(二)學程
url = 'http://sys.ndhu.edu.tw/aa/class/RuleSearch/RuleDetail.aspx?id=104,1040000008,B,AM___1042971'
數科組核心二 = get_info(url)
In [7]:
# 104 學年度統計資料分析學程
url = 'http://sys.ndhu.edu.tw/aa/class/RuleSearch/RuleDetail.aspx?id=104,1040000010,B,AM___1042971'
統計資料分析 = get_info(url)
In [8]:
# 104 學年度數學學程
url = 'http://sys.ndhu.edu.tw/aa/class/RuleSearch/RuleDetail.aspx?id=104,1040000014,B,AM___1042971'
數學 = get_info(url)
In [9]:
# 104 學年度資訊計算學程
url = 'http://sys.ndhu.edu.tw/aa/class/RuleSearch/RuleDetail.aspx?id=104,1040000013,B,AM___1042971'
資訊計算 = get_info(url)
In [10]:
# 104 學年度數學科學學程
url = 'http://sys.ndhu.edu.tw/aa/class/RuleSearch/RuleDetail.aspx?id=104,1040000119,B,AM___1042971'
數學科學 = get_info(url)
In [11]:
數科組學程名稱 = ['基礎', '數學', '數學科學', '數科組核心一', '數科組核心二', '統計資料分析', '資訊計算']
數科組學程 ={x:globals()[x] for x in 數科組學程名稱}
In [12]:
for k in 基礎.iloc[1].keys():
print(k+":", 基礎.iloc[1][k])
In [13]:
course_data = {}
for k,x in 數科組學程.items():
for i in x.index:
if i not in course_data:
#print(i, x.loc[i])
course_data[i]=dict(x.loc[i])
course_data[i]['學程'] = [k]
if not isinstance(course_data[i]['*先修科目或#背景科目'], str):
course_data[i]['*先修科目或#背景科目'] = ([], [], [], set())
else:
s = course_data[i]['*先修科目或#背景科目'].split('/')
先修 = [y[1:] for y in s if y[0]=='*']
背景 = [y[1:] for y in s if y[0]=='#']
其它 = []
多餘 = set()
course_data[i]['*先修科目或#背景科目'] =(先修, 背景, 其它, 多餘)
else:
course_data[i]['學程'].append(k)
if x.loc[i]['修別'] == '必':
course_data[i]['修別'] = '必'
In [14]:
course_data['數值方法']['學程'].append('資訊計算') # 吳建銘老師建議
趙老師建議
高等線性代數 --> 迴歸分析 <--> 實驗設計 (三下,非三上) 高等線性代數 --> 隨機模型
機率論 -> 迴歸分析
數理統計(一) -> 迴歸分析
高等線性代數 --> 隨機模型
微積分、高等線性代數、微分方程 --> 數值方法AB (三上)
In [22]:
新增列表 = {'代數(一)': ['線性代數(二)'],
'作業系統': ['程式設計(二)'],
'偏微分方程': ['高等線性代數', '高等微積分(二)', '微分方程'],
'傅氏分析': ['高等微積分(二)'],
'動態系統': ['高等線性代數', '高等微積分(二)'],
'向量分析': ['微積分(二)'],
'對局論': ['高等微積分(二)'],
'微分方程': ['線性代數(二)'],
'微陣列基因資料分析': ['數值方法'],
'拓樸學': ['高等微積分(一)'],
'數值方法': ['微積分(二)', '高等線性代數', '微分方程'],
'數論': ['數學導論'],
'演算法': ['程式設計(二)'],
'程式設計(一)': ['計算機概論'],
'程式設計(二)': ['程式設計(一)'],
'統計軟體與實務應用': ['軟體實作與計算實驗', '程式設計(二)'],
'資料結構': ['程式設計(一)'],
'軟體實作與計算實驗': ['數學導論'],
'集合論': ['分析導論'],
'離散數學': ['數學導論'],
'迴歸分析': ['高等線性代數', '機率論', '數理統計學(一)','實驗設計'],
'隨機模型': ['高等線性代數'],
'高等微積分(一)': ['分析導論']
}
for y in 新增列表.keys():
for x in 新增列表[y]:
l = course_data[y]['*先修科目或#背景科目'][2]
s = set(l)
s.add(x)
l[:] = list(s)
In [23]:
course_data.keys()
Out[23]:
In [24]:
course_data['數值方法']
Out[24]:
In [25]:
# 去除多餘
for i in range(10):
for k,v in course_data.items():
for g0 in v['*先修科目或#背景科目'][0]+v['*先修科目或#背景科目'][1]+v['*先修科目或#背景科目'][2]:
for g2 in course_data[g0]['*先修科目或#背景科目']:
for g3 in g2:
v['*先修科目或#背景科目'][-1].add(g3)
In [26]:
新增列表2 = {'實驗設計': ['迴歸分析'],
}
for y in 新增列表2.keys():
for x in 新增列表2[y]:
l = course_data[y]['*先修科目或#背景科目'][2]
s = set(l)
s.add(x)
l[:] = list(s)
In [27]:
dot = Digraph(comment="課程地圖", graph_attr={"rankdir":"LR", "ratio":"compress", "resolution":"50", "bb":"0,0,187,207"},
node_attr={"fontname":"Noto Sans CJK TC", "rank":"source", "pin":"true"})
數科組學程顏色 = {'基礎':"#aaaaaa",
'數學': "red",
'數學科學': "#7f5500",
'數科組核心一': "grey",
'數科組核心二': "black",
'統計資料分析': "blue",
'資訊計算': "green"}
數科組學程符號 = {'基礎':"🏗",
'數學': "π",
'數學科學': "🔬",
'數科組核心一': "💙",
'數科組核心二': "💕",
'統計資料分析': "📊",
'資訊計算': "💻"}
年級 = "一二三四"
level = [i+t for i in 年級 for t in "上下"]
for k,v in course_data.items():
if k.startswith("其它選修") or k=="應數專論":
continue
shape = "box"
style = "filled"
if v['修別'] == '選':
style += ", rounded"
color = {'一': "#ffeeee", "二": "#ffeeff", "三": "#ddddee", "四": "#ccddff"}[v['年級']]
l = '''<
%s <BR /> %s>'''%(k,
" ".join("<FONT POINT-SIZE='12' color='%s'>%s</FONT>"%(數科組學程顏色[z],數科組學程符號[z]) for z in sorted(v['學程'])))
dot.node(k, l, fillcolor = color, style=style, shape=shape)
dot.node('圖例', """< <TABLE>
%s </TABLE>>"""%("".join("<TR><TD><FONT POINT-SIZE='12' color='%s'>%s</FONT></TD><TD>%s</TD></TR>"%(數科組學程顏色[k], v, k) for k,v in 數科組學程符號.items())),
shape="plaintext", margin='none', pos="100,100!", pin="true")
dot.edge('代數(二)', '圖例', style='invis')
for n in level:
dot.node(n,n, style="invis")
dot.edge("一上", "數學導論", style="invis")
dot.edge("一上", "微積分(一)", style="invis")
dot.edge("一上", "計算機概論", style="invis")
#for i in range(len(level)-1):
# dot.edge(level[i], level[i+1], style="invis")
for k,v in course_data.items():
#if not v['*先修科目或#背景科目'][0]+v['*先修科目或#背景科目'][1]+v['*先修科目或#背景科目'][2]:
# dot.edge(v['年級']+v['學期'], k , style="invis")
for g in v['*先修科目或#背景科目'][0]:
if g not in v['*先修科目或#背景科目'][-1]:
dot.edge(g, k, color="blue")
for g in v['*先修科目或#背景科目'][1]:
if g not in v['*先修科目或#背景科目'][-1]:
dot.edge(g, k, color="#007f00")
for g in v['*先修科目或#背景科目'][2]:
if g not in v['*先修科目或#背景科目'][-1]:
dot.edge(g, k, color="red")
dot
Out[27]:
In [28]:
dot.render('數科組課程地圖', view=True)
Out[28]:
In [ ]: