"""
author:魏振東
date:20200303
func:微信好友性別可視化-餅狀圖
"""
from pyecharts.charts import Pie
from pyecharts import options as opts
import csv
def getSex(filename):
lstsex = []
with open(filename,'r') as f:
reader =csv.reader(f)
for i in reader:
lstsex.append(i[24])
return lstsex
def VisualSexpyechart(lstsex):
sex = dict()
for f in lstsex[1:]:
if f =='1':
sex['man'] = sex.get('man',0)+1
elif f == '2':
sex['women'] = sex.get('women',0)+1
else:
sex['unknown'] = sex.get('unknown',0)+1
total = len(lstsex[1:])
if sex['man']>sex['women']:
print("你很受大哥哥們的歡迎!男生人數比女生人數多{0}".format(sex['man']-sex['women']))
elif sex['man']<sex['women']:
print("你很受小姐姐們的歡迎!男生人數比女生人數多{0}".format(sex['women'] - sex['man']))
else:
print("男女通殺!")
attr = ['男性好友','女性好友','未知性別']
value = [sex['man'],sex['women'],sex['unknown']]
"""
class InitOpts(
# 圖表畫布寬度,css 長度單位。
width: str = "900px",
# 圖表畫布高度,css 長度單位。
height: str = "500px",
# 圖表 ID,圖表唯一標識,用於在多圖表時區分。
chart_id: Optional[str] = None,
# 渲染風格,可選 "canvas", "svg"
# # 參考 `全局變量` 章節
renderer: str = RenderType.CANVAS,
# 網頁標題
page_title: str = "Awesome-pyecharts",
# 圖表主題
theme: str = "white",
# 圖表背景顏色
bg_color: Optional[str] = None,
# 遠程 js host,如不設置默認爲 https://assets.pyecharts.org/assets/"
# 參考 `全局變量` 章節
js_host: str = "",
# 畫圖動畫初始化配置,參考 `global_options.AnimationOpts`
animation_opts: Union[AnimationOpts, dict] = AnimationOpts(),
)
"""
init_opts = opts.InitOpts(page_title="微信好友性別比例")
pie = Pie(init_opts=init_opts)
"""
class TitleOpts(
# 主標題文本,支持使用 \n 換行。
title: Optional[str] = None,
# 主標題跳轉 URL 鏈接
title_link: Optional[str] = None,
# 主標題跳轉鏈接方式
# 默認值是: blank
# 可選參數: 'self', 'blank'
# 'self' 當前窗口打開; 'blank' 新窗口打開
title_target: Optional[str] = None,
# 副標題文本,支持使用 \n 換行。
subtitle: Optional[str] = None,
# 副標題跳轉 URL 鏈接
subtitle_link: Optional[str] = None,
# 副標題跳轉鏈接方式
# 默認值是: blank
# 可選參數: 'self', 'blank'
# 'self' 當前窗口打開; 'blank' 新窗口打開
subtitle_target: Optional[str] = None,
# title 組件離容器左側的距離。
# left 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比,
# 也可以是 'left', 'center', 'right'。
# 如果 left 的值爲'left', 'center', 'right',組件會根據相應的位置自動對齊。
pos_left: Optional[str] = None,
# title 組件離容器右側的距離。
# right 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比。
pos_right: Optional[str] = None,
# title 組件離容器上側的距離。
# top 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比,
# 也可以是 'top', 'middle', 'bottom'。
# 如果 top 的值爲'top', 'middle', 'bottom',組件會根據相應的位置自動對齊。
pos_top: Optional[str] = None,
# title 組件離容器下側的距離。
# bottom 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比。
pos_bottom: Optional[str] = None,
# 標題內邊距,單位px,默認各方向內邊距爲5,接受數組分別設定上右下左邊距。
# // 設置內邊距爲 5
# padding: 5
# // 設置上下的內邊距爲 5,左右的內邊距爲 10
# padding: [5, 10]
# // 分別設置四個方向的內邊距
# padding: [
# 5, // 上
# 10, // 右
# 5, // 下
# 10, // 左
# ]
padding: Union[Sequence, Numeric] = 5,
# 主副標題之間的間距。
item_gap: Numeric = 10,
# 主標題字體樣式配置項,參考 `series_options.TextStyleOpts`
title_textstyle_opts: Union[TextStyleOpts, dict, None] = None,
# 副標題字體樣式配置項,參考 `series_options.TextStyleOpts`
subtitle_textstyle_opts: Union[TextStyleOpts, dict, None] = None,
)
"""
title = opts.TitleOpts(title="微信好友性別比例",
subtitle="好友總人數{0}".format(total),
pos_left='center')
"""
class LegendOpts(
# 圖例的類型。可選值:
# 'plain':普通圖例。缺省就是普通圖例。
# 'scroll':可滾動翻頁的圖例。當圖例數量較多時可以使用。
type_: Optional[str] = None,
# 圖例選擇的模式,控制是否可以通過點擊圖例改變系列的顯示狀態。默認開啓圖例選擇,可以設成 false 關閉
# 除此之外也可以設成 'single' 或者 'multiple' 使用單選或者多選模式。
selected_mode: Union[str, bool, None] = None,
# 是否顯示圖例組件
is_show: bool = True,
# 圖例組件離容器左側的距離。
# left 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比,
# 也可以是 'left', 'center', 'right'。
# 如果 left 的值爲'left', 'center', 'right',組件會根據相應的位置自動對齊。
pos_left: Union[str, Numeric, None] = None,
# 圖例組件離容器右側的距離。
# right 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比。
pos_right: Union[str, Numeric, None] = None,
# 圖例組件離容器上側的距離。
# top 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比,
# 也可以是 'top', 'middle', 'bottom'。
# 如果 top 的值爲'top', 'middle', 'bottom',組件會根據相應的位置自動對齊。
pos_top: Union[str, Numeric, None] = None,
# 圖例組件離容器下側的距離。
# bottom 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比。
pos_bottom: Union[str, Numeric, None] = None,
# 圖例列表的佈局朝向。可選:'horizontal', 'vertical'
orient: Optional[str] = None,
# 圖例標記和文本的對齊。默認自動(auto)
# 根據組件的位置和 orient 決定
# 當組件的 left 值爲 'right' 以及縱向佈局(orient 爲 'vertical')的時候爲右對齊,即爲 'right'。
# 可選參數: `auto`, `left`, `right`
align: Optional[str] = None,
# 圖例內邊距,單位px,默認各方向內邊距爲5
padding: int = 5,
# 圖例每項之間的間隔。橫向佈局時爲水平間隔,縱向佈局時爲縱向間隔。
# 默認間隔爲 10
item_gap: int = 10,
# 圖例標記的圖形寬度。默認寬度爲 25
item_width: int = 25,
# 圖例標記的圖形高度。默認高度爲 14
item_height: int = 14,
# 圖例關閉時的顏色。默認是 #ccc
inactive_color: Optional[str] = None,
# 圖例組件字體樣式,參考 `series_options.TextStyleOpts`
textstyle_opts: Union[TextStyleOpts, dict, None] = None,
# 圖例項的 icon。
# ECharts 提供的標記類型包括 'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'
# 可以通過 'image://url' 設置爲圖片,其中 URL 爲圖片的鏈接,或者 dataURI。
# 可以通過 'path://' 將圖標設置爲任意的矢量路徑。
legend_icon: Optional[str] = None,
)
"""
legend_opts = opts.LegendOpts(orient="vertical",
pos_top="20%",
pos_left="15%")
"""
class ToolBoxFeatureOpts(
# 保存爲圖片
save_as_image: Optional[dict] = None,
# 配置項還原
restore: Optional[dict] = None,
# 數據視圖工具,可以展現當前圖表所用的數據,編輯後可以動態更新
data_view: Optional[dict] = None,
# 數據區域縮放。目前只支持直角座標系的縮放
data_zoom: Optional[dict] = None,
)
"""
"""
class ToolboxOpts(
# 是否顯示工具欄組件
is_show: bool = True,
# 工具欄 icon 的佈局朝向。
# 可選:'horizontal', 'vertical'
orient: str = "horizontal",
# 工具欄組件離容器左側的距離。
# left 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比,
# 也可以是 'left', 'center', 'right'。
# 如果 left 的值爲'left', 'center', 'right',組件會根據相應的位置自動對齊
pos_left: str = "80%",
# 工具欄組件離容器右側的距離。
# right 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比。
pos_right: Optional[str] = None,
# 工具欄組件離容器上側的距離。
# top 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比,
# 也可以是 'top', 'middle', 'bottom'。
# 如果 top 的值爲'top', 'middle', 'bottom',組件會根據相應的位置自動對齊。
pos_top: Optional[str] = None,
# 工具欄組件離容器下側的距離。
# bottom 的值可以是像 20 這樣的具體像素值,可以是像 '20%' 這樣相對於容器高寬的百分比。
pos_bottom: Optional[str] = None,
# 各工具配置項,參考 `global_options.ToolBoxFeatureOpts`
feature: Union[ToolBoxFeatureOpts, dict] = ToolBoxFeatureOpts(),
)
"""
toolbox_opts = opts.ToolboxOpts(orient="vertical",
pos_top="35%",
pos_right="15%"
)
pie.set_global_opts(title_opts=title,
legend_opts=legend_opts,
toolbox_opts = toolbox_opts
)
"""
class LabelOpts(
# 是否顯示標籤。
is_show: bool = True,
# 標籤的位置。可選
# 'top','left','right','bottom','inside','insideLeft','insideRight'
# 'insideTop','insideBottom', 'insideTopLeft','insideBottomLeft'
# 'insideTopRight','insideBottomRight'
position: Union[str, Sequence] = "top",
# 文字的顏色。
# 如果設置爲 'auto',則爲視覺映射得到的顏色,如系列色。
color: Optional[str] = None,
# 文字的字體大小
font_size: Numeric = 12,
# 文字字體的風格,可選:
# 'normal','italic','oblique'
font_style: Optional[str] = None,
# 文字字體的粗細,可選:
# 'normal','bold','bolder','lighter'
font_weight: Optional[str] = None,
# 文字的字體系列
# 還可以是 'serif' , 'monospace', 'Arial', 'Courier New', 'Microsoft YaHei', ...
font_family: Optional[str] = None,
# 標籤旋轉。從 -90 度到 90 度。正值是逆時針。
rotate: Optional[Numeric] = None,
# 刻度標籤與軸線之間的距離。
margin: Optional[Numeric] = 8,
# 座標軸刻度標籤的顯示間隔,在類目軸中有效。
# 默認會採用標籤不重疊的策略間隔顯示標籤。
# 可以設置成 0 強制顯示所有標籤。
# 如果設置爲 1,表示『隔一個標籤顯示一個標籤』,如果值爲 2,表示隔兩個標籤顯示一個標籤,以此類推。
# 可以用數值表示間隔的數據,也可以通過回調函數控制。回調函數格式如下:
# (index:number, value: string) => boolean
# 第一個參數是類目的 index,第二個值是類目名稱,如果跳過則返回 false。
interval: Union[Numeric, str, None]= None,
# 文字水平對齊方式,默認自動。可選:
# 'left','center','right'
horizontal_align: Optional[str] = None,
# 文字垂直對齊方式,默認自動。可選:
# 'top','middle','bottom'
vertical_align: Optional[str] = None,
# 標籤內容格式器,支持字符串模板和回調函數兩種形式,字符串模板與回調函數返回的字符串均支持用 \n 換行。
# 模板變量有 {a}, {b},{c},{d},{e},分別表示系列名,數據名,數據值等。
# 在 trigger 爲 'axis' 的時候,會有多個系列的數據,此時可以通過 {a0}, {a1}, {a2} 這種後面加索引的方式表示系列的索引。
# 不同圖表類型下的 {a},{b},{c},{d} 含義不一樣。 其中變量{a}, {b}, {c}, {d}在不同圖表類型下代表數據含義爲:
# 折線(區域)圖、柱狀(條形)圖、K線圖 : {a}(系列名稱),{b}(類目值),{c}(數值), {d}(無)
# 散點圖(氣泡)圖 : {a}(系列名稱),{b}(數據名稱),{c}(數值數組), {d}(無)
# 地圖 : {a}(系列名稱),{b}(區域名稱),{c}(合併數值), {d}(無)
# 餅圖、儀表盤、漏斗圖: {a}(系列名稱),{b}(數據項名稱),{c}(數值), {d}(百分比)
# 示例:formatter: '{b}: {@score}'
#
# 回調函數,回調函數格式:
# (params: Object|Array) => string
# 參數 params 是 formatter 需要的單個數據集。格式如下:
# {
# componentType: 'series',
# // 系列類型
# seriesType: string,
# // 系列在傳入的 option.series 中的 index
# seriesIndex: number,
# // 系列名稱
# seriesName: string,
# // 數據名,類目名
# name: string,
# // 數據在傳入的 data 數組中的 index
# dataIndex: number,
# // 傳入的原始數據項
# data: Object,
# // 傳入的數據值
# value: number|Array,
# // 數據圖形的顏色
# color: string,
# }
formatter: Optional[str] = None,
# 在 rich 裏面,可以自定義富文本樣式。利用富文本樣式,可以在標籤中做出非常豐富的效果
# 具體配置可以參考一下 https://www.echartsjs.com/tutorial.html#%E5%AF%8C%E6%96%87%E6%9C%AC%E6%A0%87%E7%AD%BE
rich: Optional[dict] = None,
)
"""
"""
def add(
# 系列名稱,用於 tooltip 的顯示,legend 的圖例篩選。
series_name: str,
# 系列數據項,格式爲 [(key1, value1), (key2, value2)]
data_pair: Sequence,
# 系列 label 顏色
color: Optional[str] = None,
# 餅圖的半徑,數組的第一項是內半徑,第二項是外半徑
# 默認設置成百分比,相對於容器高寬中較小的一項的一半
radius: Optional[Sequence] = None,
# 餅圖的中心(圓心)座標,數組的第一項是橫座標,第二項是縱座標
# 默認設置成百分比,設置成百分比時第一項是相對於容器寬度,第二項是相對於容器高度
center: Optional[Sequence] = None,
# 是否展示成南丁格爾圖,通過半徑區分數據大小,有'radius'和'area'兩種模式。
# radius:扇區圓心角展現數據的百分比,半徑展現數據的大小
# area:所有扇區圓心角相同,僅通過半徑展現數據大小
rosetype: Optional[str] = None,
# 餅圖的扇區是否是順時針排布。
is_clockwise: bool = True,
# 標籤配置項,參考 `series_options.LabelOpts`
label_opts: Union[opts.LabelOpts, dict] = opts.LabelOpts(),
# 提示框組件配置項,參考 `series_options.TooltipOpts`
tooltip_opts: Union[opts.TooltipOpts, dict, None] = None,
# 圖元樣式配置項,參考 `series_options.ItemStyleOpts`
itemstyle_opts: Union[opts.ItemStyleOpts, dict, None] = None,
)
"""
pie.add("",
[list(z) for z in zip(attr,value)],
radius=[30, 75],
center=['50%','50%'],
rosetype ="area",
label_opts=opts.LabelOpts(
position="outside",
formatter="{b|{b}: }{c} {per|{d}%} ",
background_color="#eee",
border_color="#aaa",
border_width=1,
border_radius=4,
rich={
"a": {"color": "#999", "lineHeight": 22, "align": "center"},
"abg": {
"backgroundColor": "#e3e3e3",
"width": "100%",
"align": "right",
"height": 22,
"borderRadius": [4, 4, 0, 0],
},
"hr": {
"borderColor": "#aaa",
"width": "100%",
"borderWidth": 0.5,
"height": 0,
},
"b": {"fontSize": 16, "lineHeight": 33},
"per": {
"color": "#eee",
"backgroundColor": "#334455",
"padding": [2, 4],
"borderRadius": 2,
},
},
),
)
pie.render('微信好友性別比例.html')
VisualSexpyechart(getSex("data/wudifriendsalldata.csv"))
"""
author:魏振東
date:20200303
func:數據可視化-餅狀圖
"""
from pyecharts.charts import Pie
from pyecharts import options as opts
import xlrd
def getSex(filename, num):
lstsex=[]
data = xlrd.open_workbook(filename, 'r', encoding_override='utf-8')
table = data.sheets()[num]
for i in range(1,table.nrows) :
lstsex.append(table.row_values(i)[5])
return lstsex
def VisualSexpyechart(lstsex171,lstsex172):
sex = dict()
s=0
for f in lstsex171:
if f == '男':
sex["男"] = sex.get("男", 0) + 1
elif f == '女':
sex["女"] = sex.get("女", 0) + 1
total171 = len(lstsex171)
attr = ['171男生', '171女生']
value = [sex["男"], sex["女"]]
list171 = [list(z) for z in zip(attr,value)]
sex1 = dict()
for f in lstsex172:
if f == '男':
sex1["男"] = sex1.get("男", 0) + 1
elif f == '女':
sex1["女"] = sex1.get("女", 0) + 1
total172 = len(lstsex172)
attr1 = ['172男生', '172女生']
value1 = [sex1["男"], sex1["女"]]
list172 = [list(z) for z in zip(attr1,value1)]
init_opts = opts.InitOpts(page_title="171-172男女比例餅狀圖")
pie = Pie(init_opts=init_opts)
title = opts.TitleOpts(title="171-172男女比例餅狀圖",
subtitle="171班總人數{0} 172班總人數{1}".format(total171,total172),
pos_left='center')
legend_opts = opts.LegendOpts(orient="vertical",
pos_top="20%",
pos_left="15%")
toolbox_opts = opts.ToolboxOpts(orient="vertical",
pos_top="25%",
pos_right="15%"
)
pie.set_global_opts(title_opts=title,
legend_opts=legend_opts,
toolbox_opts=toolbox_opts
)
pie.add("",
list171,
radius=[0, 75],
center=['50%', '30%'],
rosetype="radius",
label_opts=opts.LabelOpts(formatter="{b}:{c} ")
)
pie.add("",
list172,
radius=[30, 75],
center=['50%', '70%'],
rosetype="area",
label_opts=opts.LabelOpts(
position="outside",
formatter="{b|{b}: }{c} {per|{d}%} ",
background_color="#eee",
border_color="#aaa",
border_width=1,
border_radius=4,
rich={
"a": {"color": "#999", "lineHeight": 22, "align": "center"},
"abg": {
"backgroundColor": "#e3e3e3",
"width": "100%",
"align": "right",
"height": 22,
"borderRadius": [4, 4, 0, 0],
},
"hr": {
"borderColor": "#aaa",
"width": "100%",
"borderWidth": 0.5,
"height": 0,
},
"b": {"fontSize": 16, "lineHeight": 33},
"per": {
"color": "#eee",
"backgroundColor": "#334455",
"padding": [2, 4],
"borderRadius": 2,
},
},
),
)
pie.render('171-172男女比例餅狀圖.html')
VisualSexpyechart(getSex('../data/軟件17學生詳細名單.xls',0),getSex('../data/軟件17學生詳細名單.xls',1))