1 
 
Python 匯出入 CSV 以及繪製圖表
一、 環境設定
物聯網很多系統都是基於 Linux 的環境進行開發設計,所以本課程將環境預設
為 ubunutu 環境。請您於 ubuntu 軟體中心內搜尋「python」,再請您安裝
python3.4 以及編輯軟體 Spyder。
Spyder 具有語法檢察功能,可避免 python 語法出錯,也可透過 Spyder 上的
run 執行 python 程式。Spyder 利用 Interpreters 視窗執行 python,若您覺得
Interpreters 視窗內訊息太複雜,可關閉該視窗,再請點選「Interpreters」
內「Open a Python interpreter」。
【圖 1、於 ubuntu 環境內安裝 python 與編輯軟體】
接著我們需要兩個 python 模組,一個是 numpy 數學計算模組,一個是
matplotlib 統計圖表模組,請您開啟終端機程式,輸入以下兩行指令:
sudo apt-get install python-numpy
sudo apt-get install python-matplotlib
完成了環境設定後,接下來我們將要提兩個主題,第一個主題是 csv 檔案的存
取,第二個主題是圖表顯示。
2 
 
二、 csv 檔案的存取
CSV 是一個常用的資料格式,我們可藉由 Python 讀取 CSV 檔案內容,也可透
過 Python 將資料寫入 CSV 檔案內。由於 Linux 環境內的 CSV 檔案預設編碼為
UTF-8,建議您如果是在 Windows 環境內,請不要使用 Excel,請改用 LibreOffice
Calc 進行編碼處理。由於 Python 中 2.7.x 的 CSV 模組不支援 Unicode,所以程
式的第 1 行我們會加入「# -*- coding: utf-8 -*-」進行編碼設定。例如我們
將讀取以下的 csv 檔案內容(data2.csv):
dataname,data1,data2
a,100,555
b,234,343
c,234,23
d,23,44
e,45,334
f,23,345
這個 CSV 檔案第一列為標題,第二列起才是真實的資料,我們在讀取檔案內容
時須將這兩部分切割(檔名為 csv.py):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
# -*- coding: utf-8 -*-
import csv
filename = 'data2.csv'
data = []
try:
with open(filename) as f:
reader = csv.reader(f)
header = reader.next()
data = [row for row in reader]
except csv.Error as e:
print "Error reading CSV file at line %s: %s" % (reader.line_num,
e)
if header:
print header
print '=================='
for datarow in data:
print datarow
3 
 
【圖 2、讀取 csv 並將第一列與其他列分開】
第 1 行語法的目的是設定檔案的編碼為 UTF-8,第 2 行匯入 python 的 CSV 模
組,第 3 行設定 filename 變數的內容是 data2.csv。透過 open 語法開啟 filename
變數,產生一個繫結至物件 f。第 6 行 with 語法可以控制物件 f 操作完成後可
被釋放關閉。第 7 行使用 csv.reader()讀取所有資料後儲存於 reader 陣列,第
8 行 reader 陣列的第一筆資料交給 header 後指標指向下一筆紀錄,接著第 9 行
剩下的資料交給 data 陣列儲存。
第 12 行條件分析後如果 header 存在則輸出 header 內容,接著第 15 行以 for
迴圈控制,逐一由 data 陣列讀取每一筆資料後儲存於 datarow 變數內,再將
datarow 變數輸出。這個練習中也使用了例外處理,第 5 行設置 try 區塊放入 with
語法,如果 with 語法執行過程中有發生狀況,程式會暫停執行,跳至第 10 行
except 這個區塊內輸出 Error 訊息。
在此提供 example.csv 檔案內如如下,這是一個以「,」為分隔符號的 CSV 檔
案:
日期,成交股數,成交金額,成交筆數,發行量加權股價指數,漲跌點數
104/01/02,"2,104,640,545","50,472,201,894","497,889","6,952.21",-119.
87
104/01/03,"2,640,781,030","64,138,886,194","623,192","7,053.38",101.1
7
104/01/04,"2,983,756,821","75,845,629,353","728,417","7,082.97",29.59
104/01/05,"3,062,757,248","76,850,752,698","737,780","7,130.86",47.89
104/01/06,"3,314,147,435","88,101,921,548","823,810","7,120.51",-10.3
5
4 
 
104/01/09,"2,610,433,477","71,323,370,369","634,137","7,093.04",-27.4
7
104/01/10,"3,595,611,551","97,168,542,017","869,327","7,178.87",85.83
104/01/11,"3,322,390,467","88,786,671,892","802,539","7,188.21",9.34
104/01/12,"2,969,248,375","78,947,910,460","731,328","7,186.58",-1.63
104/01/13,"3,497,838,901","99,286,437,370","819,762","7,181.54",-5.04
104/01/16,"3,184,795,667","76,842,611,338","719,725","7,103.62",-77.9
2
104/01/17,"3,720,277,205","101,133,309,290","899,597","7,221.08",117.
46
104/01/18,"4,088,756,925","113,988,641,382","1,020,420","7,233.69",12
.61
104/01/30,"4,540,373,544","143,900,658,474","1,113,727","7,407.41",17
3.72
104/01/31,"5,486,734,180","162,361,181,834","1,283,951","7,517.08",10
9.67
於 unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 csv2.py):
1
2
3
4
5
6
# -*- coding: utf-8 -*-
import csv
f=open('example.csv',"r")
for row in csv.DictReader(f):
print(row['日期'])
f.closed
5 
 
【圖 3、讀取 CSV 檔案的指定一欄內容】
第 1 行語法的目的是設定檔案的編碼為 UTF-8,第 2 行匯入 python 的 CSV 模
組,第 3 行建立 python 與 CSV 檔案的連結物件,這一行連結 example.csv 檔案,
連結屬性為「讀取」,物件名稱為 f。第 4 行建立一個迴圈,透過 csv.DictReader
逐行讀取 f 物件資料,並以陣列型式儲存於 row 陣列。第 5 行輸出 row 陣列的「日
期」欄位內容,第 6 行關閉銷毀 f 物件。
讀取出來的資料可再做進一步的分析,請於 unbuntu 內請開啟 Spyder 編輯
python 文件後執行(檔名為 csv-3-1.py):
1
2
3
4
5
6
7
# -*- coding: utf-8 -*-
import csv
f=open('example.csv',"r")
for row in csv.DictReader(f):
if float(row['漲跌點數'])>9.34 :
print(row['漲跌點數'])
f.closed
【圖 4、讀取 CSV 檔案後指定特定欄位進行資料分析】
6 
 
第 5 行將 row 陣列的「漲跌點數」欄位內容轉換為浮點數型態後判斷是否大於
9.34,若條件成立則將「漲跌點數」欄位內容輸出。
讀取出來的資料欄位名稱可以更進一步簡化為特定的代碼,「漲跌點數」欄位
是第 6 個欄位,若依照英文字母排列則是 f,請於 unbuntu 內請開啟 Spyder 編
輯 python 文件後執行(檔名為 csv-3.py):
01
02
03
04
05
06
07
08
09
# -*- coding: utf-8 -*-
import csv
f=open('example.csv',"r")
for row in csv.DictReader(f,['a','b','c','d','e','f']):
if float(row['f'])>71 :
print(row['f'])
else:
print("error")
f.closed
【圖 5、讀取 CSV 檔案後將欄位名稱簡化為特定代碼並做條件分析】
第 4 行建立一個迴圈,透過 csv.DictReader 逐行讀取 f 物件資料,讀取 f 物
件資料後依序放入規劃欄位名稱為 a、c、d、e、f 的 row 陣列內。第 5 行將 row
陣列的「f」欄位內容轉換為浮點數型態後判斷是否大於 71,若條件成立則將「f」
欄位內容輸出,若不成立則輸出「error」。
除了讀取資料,我們也可以寫入資料到 CSV 檔案內,寫入的方式有兩種,「a」
代表附加,若檔案存在則會在原有內容後附加上去;「w」代表覆蓋,若檔案存在
則會刪除原內容後添加新資料。請於 unbuntu 內請開啟 Spyder 編輯 python 文件
後執行(檔名為 csv-4a.py):
1
2
3
4
5
6
# -*- coding: utf-8 -*-
import csv
data=[['a','b',100,3.5],['x','y',200,7.5]]
f=open("test2.csv","a")
f.writerows(data)
f.closed
請查看 test2.csv 檔案內容,另請修改第 4 行的"a"為"w",另存新檔(例如
csv-4b.py)後再執行,再請查看 test2.csv 檔案內容。
7 
 
儲存 CSV 檔案時也可挑選其他格式,請於 unbuntu 內請開啟 Spyder 編輯 python
文件後執行(檔名為 csv-5.py):
1
2
3
4
5
6
# -*- coding: utf-8 -*-
import csv
with open('eggs.csv','w') as csvfile:
s=csv.writer(csvfile,delimiter='-',quotechar="|",quoting=csv.QUOTE_MINIMA
L)
s.writerow(['Spam1','Spam2','Spam3'])
s.writerow(['Spam11','Spam21','Spam31'])
第 3 行進行檔案連結處理,以 w 寫入方式開啟 eggs.csv 檔案,第 4 行則要進
行寫入的格式設定。第 4 行有三個參數,如表 1 的說明。
參數 說明
delimiter 代表分隔符號
quotechar 代表包住字串的符號
quoting 插入到 CSV 文件中的一行記錄加入 quotechar 的方式
【表 1、儲存 CSV 檔案時挑選其他格式】
插入到 CSV 文件中的一行記錄加入 quotechar 的方式可參考表 2 的說明。
quoting 說明
csv.QUOTE_ALL 不論任何類型,全部都可以設定為符號。
csv.QUOTE_MINIMAL 使用特殊字元的欄位。
csv.QUOTE_NONNUMERIC 使用不是數字的欄位。
csv.QUOTE_NONE 不使用輸出的任何資料。
【表 2、插入到 CSV 文件中的一行記錄加入 quotechar 的方式】
特殊 csv 檔案格式內容如下:
|Spam1|-|Spam2|-|Spam3|
|Spam11|-|Spam21|-|Spam31|
三、 圖表顯示
進行圖表顯示之前,我們可利用終端機環境內互動的方式立即產生圖表,請於
終端機內啟動 ipython:
ipython --pylab
接著請您輸入以下的資料:
plot([1,2,3,2,3,2,2,1])
8 
 
您會看到這邊產生了一個圖表。
【圖 6、ipython 產生的圖表:y 軸給值】
這圖表可以分為好幾個區域,在此略作說明如下:
x and y axis:x 是水平的軸線、y 是垂直的軸線。
x and y tickers:代表 x 軸與 y 軸的刻度,這刻度代表坐標軸的分隔,包括最
小與最大的刻度。
x and y values:代表 x 軸與 y 軸的刻度內容
figure:畫布,圖表繪製於上。
9 
 
【圖 7、figure 畫面說明】
前面的資料只提供 y 值,x 軸為默認值,因 plot()內參數有 7 個,所以 x 由 0
到 7 進行繪圖。現在嘗試加入 x 軸的值,我們來看看畫面會如何顯示。請於終端
機內啟動 ipython:
ipython --pylab
接著請您輸入以下的資料:
plot([3,4,6],[2,7,5])
10 
 
【圖 8、ipython 產生的圖表:x 軸與 y 軸給值】
前面為 X 軸,後面為 Y 軸的方式給值。您也可以合併兩個數據後輸出,比如說
延續上個練習,接著請您輸入以下的資料:
plot([9,8,7])
【圖 9、ipython 產生兩個圖表】
畫面上將會出現兩個圖表資訊,所以您可使用 ipython 於終端機測試,再開始
寫程式。
1、 基本繪圖說明
我們試著在一個文件上繪製六個圖表,藉此了解各種基本繪圖指令。請於
unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 1.py):
01
02
03
04
05
06
07
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
x = [1,2,3,4]
y = [5,4,3,2]
plt.figure()
plt.subplot(231)
plt.plot(x, y)
11 
 
08
09
10
11
12
13
14
15
16
17
18
19
20
plt.subplot(232)
plt.bar(x, y)
plt.subplot(233)
plt.barh(x, y)
plt.subplot(234)
plt.bar(x, y)
y1 = [7,8,5,3]
plt.bar(x, y1, bottom=y, color = 'r')
plt.subplot(235)
plt.boxplot(x)
plt.subplot(236)
plt.scatter(x,y)
plt.show()
【圖 10、切割成 6 等份顯示圖表】
這一張圖的資訊非常豐富,我們可以一張一張繪製,不過為了讓您了解 python
功能的強大,這邊選擇一次繪製六張圖表。
12 
 
透過 figure 動作可以建立一個畫布,於這畫布上可透過 plot()做基本的繪圖,
plot()可對x 座標及相對應的y 座標進行繪製。若於畫布上寫要繪製多張圖表,
可使用 subplot()這個動作,subplot()動作內可加入三個參數,我們以 mnp 來
表示,可以切割為 m 乘以 n 個區域,而 p 代表第幾個位置。接著各單元可簡介各
種圖表的規劃設計。
2、 長條圖
長條圖樣式將會使用 bar()這動作,bar()的參數樣式很多,可以使用 bar(X,Y)
代表 x 軸位置與 y 軸內容,或者可用 bar(X,Y,width)代表 x 軸位置與 y 軸內容
及寬度;bar (x, y1, bottom=y, color = 'r')代表 x 為 x 軸位置,y1 為 y 軸
內容,顏色為紅色,而「bottom=y」代表堆疊。橫向長條圖可用 barh()動作操
作,參數與 bar()相同,只是方向不同。
我們試著在一個文件上繪製長條圖,藉由數量的不同進行區間的調整。請於
unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 2.py):
1
2
3
4
5
6
7
8
9
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
y = [3, 10, 7, 5, 3, 4.5, 6, 8.1]
N = len(y)
x = range(N)
width = 1/1.5
plt.figure()
plt.bar(x, y, width, color="blue")
plt.show( )
13 
 
【圖 11、基本的長條圖】
接著我們對資料進行格式化動作,X 軸上出現說明文字,以及給予每一個座標
內容,我們規劃了三個長條圖,內容分別為 26、17、30,X 軸上顯示 Label0、
Label1、Label2。請於 unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名
為 3.py):
1
2
3
4
5
6
7
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
dictionary = plt.figure()
D = {u'Label0':26, u'Label1': 17, u'Label2':30}
plt.bar(range(len(D)), D.values(), align='center')
plt.xticks(range(len(D)), D.keys())
plt.show( )
14 
 
【圖 12、設定標籤的長條圖】
接下來的設計就稍微複雜了,我們不僅將兩種資料合併在一個長條圖上,且設
定了 X 軸與 Y 軸的刻度標籤。請於 unbuntu 內請開啟 Spyder 編輯 python 文件後
執行(檔名為 4.py):
01
02
03
04
05
06
07
08
09
10
11
12
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
mpl_fig = plt.figure()
ax = mpl_fig.add_subplot(111)
N = 5
menMeans = (20, 35, 30, 35, 27)
womenMeans = (25, 32, 34, 20, 25)
menStd = (2, 3, 4, 1, 2)
womenStd = (3, 5, 2, 3, 3)
ind = np.arange(N)
width = 0.35
15 
 
13
14
15
16
17
18
19
20
21
22
p1 = ax.bar(ind, menMeans, width, color=(0.2588,0.4433,1.0))
p2 = ax.bar(ind, womenMeans, width, color=(1.0,0.5,0.62),
bottom=menMeans)
ax.set_ylabel('Scores')
ax.set_xlabel('Groups')
ax.set_title('Scores by group and gender')
ax.set_xticks(ind + width/2.)
ax.set_yticks(np.arange(0, 81, 10))
ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5'))
plt.show( )
【圖 13、設定刻度標籤的長條圖】
下一個練習我們就會將三組資料依據時間以不同顏色顯示。請於 unbuntu 內請
開啟 Spyder 編輯 python 文件後執行(檔名為 5.py):
01
02
03
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib.dates import date2num
16 
 
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
import datetime
multiple_bars = plt.figure()
x = [datetime.date(2016, 1, 4),
datetime.date(2016, 1, 5),
datetime.date(2016, 1, 6)]
x = date2num(x)
y = [4, 9, 2]
z=[1,2,3]
k=[11,12,13]
ax = plt.subplot(111)
ax.bar(x-0.2, y,width=0.2,color='b',align='center')
ax.bar(x, z,width=0.2,color='g',align='center')
ax.bar(x+0.2, k,width=0.2,color='r',align='center')
ax.xaxis_date()
plt.show()
【圖 14、依據時間分組的長條圖】
下一個練習我們將於 X 軸與 Y 軸加上標籤,並且於圖表文件上加上圖例說明文
17 
 
字。請於 unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 5a.py):
01
02
03
04
05
06
07
08
09
10
11
12
13
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 10, 1)
y = np.log(x)
xe = 0.1 * np.abs(np.random.randn(len(y)))
plt.bar(x, y, yerr=xe, width=0.4, align='center', ecolor='r',
color='cyan', label='experiment #1');
plt.xlabel('# measurement')
plt.ylabel('Measured values')
plt.title('Measurements')
plt.legend(loc='upper left')
plt.show()
【圖 15、加上圖例說明的長條圖】
3、 盒狀圖
18 
 
盒狀圖可用 boxplot( )規劃,盒狀圖的目的是顯示資料集合的整個範圍分布,
在一個盒狀圖內可以顯示出五種資訊。
1. 最小值:資料集合中的最小值資料。
2. 第二四分位數:資料集合中較低的 25%資料。
3. 中間值:資料集合中位於 50%資料。
4. 第三四分位數:資料集合中的 75%資料。
5. 最大值:資料集合中的最大值資料。
我們將設計一個基本的盒狀圖。請於 unbuntu 內請開啟 Spyder 編輯 python
文件後執行(檔名為 6.py):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
spread = np.random.rand(50) * 100
center = np.ones(25) * 50
flier_high = np.random.rand(10) * 100 + 100
flier_low = np.random.rand(10) * -100
data = np.concatenate((spread, center, flier_high, flier_low), 0)
mpl_fig = plt.figure()
ax = mpl_fig.add_subplot(111)
ax.boxplot(data)
ax.set_xlabel('Data Points')
ax.set_ylabel('Variance')
plt.show()
19 
 
【圖 16、基本的盒狀圖】
我們將設計多個盒狀圖,顯示隨機取數下資料的變化。請於 unbuntu 內請開啟
Spyder 編輯 python 文件後執行(檔名為 7.py):
01
02
03
04
05
06
07
08
09
10
11
12
13
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
N = 1000
data_set1 = np.random.normal(1, 1, N)
data_set2 = np.random.lognormal(1, 1, N)
data_set3 = np.random.exponential(1, N)
data_set4 = np.random.gumbel(6, 4, N)
data_set5 = np.random.triangular(2, 9, 11, N)
data = [data_set1, data_set2, data_set3, data_set4, data_set5]
mpl_fig = plt.figure()
ax = mpl_fig.add_subplot(111)
20 
 
14
15
ax.boxplot(data)
plt.show()
【圖 17、多個盒狀圖】
4、 散佈圖
散佈圖是將兩個可能相關的變數資料用點畫在坐標圖上,用成對的資料之間是
否有相關性。這種成對的資料或許是特性一原因,特性一特性一原因的關係。通
過對其觀察分析,來判斷兩個變數之間的相關關係。
我們將設計一個基本的散佈圖,資料以隨機方式產生。請於 unbuntu 內請開啟
Spyder 編輯 python 文件後執行(檔名為 8.py):
01
02
03
04
05
06
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
fig, ax = plt.subplots()
ax.scatter(np.linspace(-1, 1, 50), np.random.randn(50))
21 
 
07 plt.show()
【圖 18、基本散佈圖】
接著我們藉由透明度的設計讓散佈圖有不一樣的變化,請於 unbuntu 內請開啟
Spyder 編輯 python 文件後執行(檔名為 9.py):
01
02
03
04
05
06
07
08
09
10
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
x = np.random.normal(size = 2000)
y = np.random.normal(size = 2000)
plt.scatter(x, y, alpha = 0.3)
plt.title("scatterplot")
plt.xlabel("x")
plt.ylabel("y")
plt.show()
22 
 
【圖 19、具透明度的散佈圖】
除了透明度的設計,我們也可以隨機方式改變散佈圖的大小,請於 unbuntu
內請開啟 Spyder 編輯 python 文件後執行(檔名為 10.py):
01
02
03
04
05
06
07
08
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
x = np.random.rand(500)
y = np.random.rand(500)
z = np.random.normal(size = 500)
plt.scatter(x, y, s = z * 200, alpha = 0.4)
plt.show()
23 
 
【圖 20、具透明度與不同大小的散佈圖】
四、 圖表的屬性與格式
接著將為您整理圖表的各式屬性與顏色,將能幫助您設計變化更多的圖表。
1、 線條屬性
以下列表則是說明圖表中的線條屬性:
24 
 
屬性 類型 描述
alpha 浮點數 Alpha值用來設置混色,並
不是所有項目都可以支持
color or c 任意 matplotlib 顏色 設置線條顏色.
dashes 以點為單位的 on/off 序列 設置破折號序列,如果seq
為空或者seq = (None,
None),那麼linestyle 將
會被設定為 solid.
label 任意字串 為各種圖例說明所設定的
標籤
linestyle 或 ls [ '-' | '–' | '-.' | ':' |
'steps' | ...]
設定線條風格 (也可以接
受 drawstyles內容).
linewidth 或 lw 以點為單位的浮點數型態數
值
設定以點為單位的線條寬
度.
marker [ 7 | 4 | 5 | 6 | 'o' | 'D'
| 'h' | 'H' | '_' | '' |
'None' | ' ' | None | '8' |
'p' | ',' | '+' | '.' | 's'
| '*' | 'd' | 3 | 0 | 1 | 2
| '1' | '3' | '4' | '2' | 'v'
| '<' | '>' | '^' | '|' | 'x'
| '$...$' | tuple | Nx2
array ]
設定線條標記
markeredgecolor 或
mec
任何 matplotlib 顏色 設定標記的邊緣顏色
markeredgewidth或
mew
以點為單位的浮點數型態數
值
設定標記的邊緣寬度
markerfacecolor 或
mfc
任何 matplotlib 顏色 設定標記的顏色
markersize 或 ms 浮點數 設定以點為單位的標記大
小
solid_capstyle ['butt' | 'round' |
'projecting']
設定實線的線端風格
solid_joinstyle ['miter' | 'round' | 設定實線的連接風格.
25 
 
'bevel']
visible [True | False] 顯示或隱藏
xdata np.array 設定x的np.array內容
ydata np.array 設定y的np.array內容
【表 3、線條屬性】
2、 線條風格與顏色
以下列表則是說明圖表中的線條風格:
線條風格 描述 線條風格 描述
'-' 實線 '-.' 點划線
'--' 破折線 ':' 虛線
'None', ' ', '' 甚麼都不畫
【表 4、線條風格】
以下列表則是說明圖表中的顏色
顏色 說明 顏色 說明
b 藍色 g 綠色
r 紅色 y 黃色
c 青色 k 黑色
m 洋紅色 w 白色
【表 5、顏色】
上述表格提供基本的顏色部分設定,若上述表格提供的顏色不符合需求,您可
以使用網頁的十六進位字串方式定義顏色,例如:color='#fe3465',就可以
做更複雜的顏色變化。

Python匯出入csv以及繪製圖表初稿

  • 1.
    1    Python 匯出入 CSV以及繪製圖表 一、 環境設定 物聯網很多系統都是基於 Linux 的環境進行開發設計,所以本課程將環境預設 為 ubunutu 環境。請您於 ubuntu 軟體中心內搜尋「python」,再請您安裝 python3.4 以及編輯軟體 Spyder。 Spyder 具有語法檢察功能,可避免 python 語法出錯,也可透過 Spyder 上的 run 執行 python 程式。Spyder 利用 Interpreters 視窗執行 python,若您覺得 Interpreters 視窗內訊息太複雜,可關閉該視窗,再請點選「Interpreters」 內「Open a Python interpreter」。 【圖 1、於 ubuntu 環境內安裝 python 與編輯軟體】 接著我們需要兩個 python 模組,一個是 numpy 數學計算模組,一個是 matplotlib 統計圖表模組,請您開啟終端機程式,輸入以下兩行指令: sudo apt-get install python-numpy sudo apt-get install python-matplotlib 完成了環境設定後,接下來我們將要提兩個主題,第一個主題是 csv 檔案的存 取,第二個主題是圖表顯示。
  • 2.
    2    二、 csv 檔案的存取 CSV是一個常用的資料格式,我們可藉由 Python 讀取 CSV 檔案內容,也可透 過 Python 將資料寫入 CSV 檔案內。由於 Linux 環境內的 CSV 檔案預設編碼為 UTF-8,建議您如果是在 Windows 環境內,請不要使用 Excel,請改用 LibreOffice Calc 進行編碼處理。由於 Python 中 2.7.x 的 CSV 模組不支援 Unicode,所以程 式的第 1 行我們會加入「# -*- coding: utf-8 -*-」進行編碼設定。例如我們 將讀取以下的 csv 檔案內容(data2.csv): dataname,data1,data2 a,100,555 b,234,343 c,234,23 d,23,44 e,45,334 f,23,345 這個 CSV 檔案第一列為標題,第二列起才是真實的資料,我們在讀取檔案內容 時須將這兩部分切割(檔名為 csv.py): 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 # -*- coding: utf-8 -*- import csv filename = 'data2.csv' data = [] try: with open(filename) as f: reader = csv.reader(f) header = reader.next() data = [row for row in reader] except csv.Error as e: print "Error reading CSV file at line %s: %s" % (reader.line_num, e) if header: print header print '==================' for datarow in data: print datarow
  • 3.
    3    【圖 2、讀取 csv並將第一列與其他列分開】 第 1 行語法的目的是設定檔案的編碼為 UTF-8,第 2 行匯入 python 的 CSV 模 組,第 3 行設定 filename 變數的內容是 data2.csv。透過 open 語法開啟 filename 變數,產生一個繫結至物件 f。第 6 行 with 語法可以控制物件 f 操作完成後可 被釋放關閉。第 7 行使用 csv.reader()讀取所有資料後儲存於 reader 陣列,第 8 行 reader 陣列的第一筆資料交給 header 後指標指向下一筆紀錄,接著第 9 行 剩下的資料交給 data 陣列儲存。 第 12 行條件分析後如果 header 存在則輸出 header 內容,接著第 15 行以 for 迴圈控制,逐一由 data 陣列讀取每一筆資料後儲存於 datarow 變數內,再將 datarow 變數輸出。這個練習中也使用了例外處理,第 5 行設置 try 區塊放入 with 語法,如果 with 語法執行過程中有發生狀況,程式會暫停執行,跳至第 10 行 except 這個區塊內輸出 Error 訊息。 在此提供 example.csv 檔案內如如下,這是一個以「,」為分隔符號的 CSV 檔 案: 日期,成交股數,成交金額,成交筆數,發行量加權股價指數,漲跌點數 104/01/02,"2,104,640,545","50,472,201,894","497,889","6,952.21",-119. 87 104/01/03,"2,640,781,030","64,138,886,194","623,192","7,053.38",101.1 7 104/01/04,"2,983,756,821","75,845,629,353","728,417","7,082.97",29.59 104/01/05,"3,062,757,248","76,850,752,698","737,780","7,130.86",47.89 104/01/06,"3,314,147,435","88,101,921,548","823,810","7,120.51",-10.3 5
  • 4.
    4    104/01/09,"2,610,433,477","71,323,370,369","634,137","7,093.04",-27.4 7 104/01/10,"3,595,611,551","97,168,542,017","869,327","7,178.87",85.83 104/01/11,"3,322,390,467","88,786,671,892","802,539","7,188.21",9.34 104/01/12,"2,969,248,375","78,947,910,460","731,328","7,186.58",-1.63 104/01/13,"3,497,838,901","99,286,437,370","819,762","7,181.54",-5.04 104/01/16,"3,184,795,667","76,842,611,338","719,725","7,103.62",-77.9 2 104/01/17,"3,720,277,205","101,133,309,290","899,597","7,221.08",117. 46 104/01/18,"4,088,756,925","113,988,641,382","1,020,420","7,233.69",12 .61 104/01/30,"4,540,373,544","143,900,658,474","1,113,727","7,407.41",17 3.72 104/01/31,"5,486,734,180","162,361,181,834","1,283,951","7,517.08",10 9.67 於 unbuntu 內請開啟Spyder 編輯 python 文件後執行(檔名為 csv2.py): 1 2 3 4 5 6 # -*- coding: utf-8 -*- import csv f=open('example.csv',"r") for row in csv.DictReader(f): print(row['日期']) f.closed
  • 5.
    5    【圖 3、讀取 CSV檔案的指定一欄內容】 第 1 行語法的目的是設定檔案的編碼為 UTF-8,第 2 行匯入 python 的 CSV 模 組,第 3 行建立 python 與 CSV 檔案的連結物件,這一行連結 example.csv 檔案, 連結屬性為「讀取」,物件名稱為 f。第 4 行建立一個迴圈,透過 csv.DictReader 逐行讀取 f 物件資料,並以陣列型式儲存於 row 陣列。第 5 行輸出 row 陣列的「日 期」欄位內容,第 6 行關閉銷毀 f 物件。 讀取出來的資料可再做進一步的分析,請於 unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 csv-3-1.py): 1 2 3 4 5 6 7 # -*- coding: utf-8 -*- import csv f=open('example.csv',"r") for row in csv.DictReader(f): if float(row['漲跌點數'])>9.34 : print(row['漲跌點數']) f.closed 【圖 4、讀取 CSV 檔案後指定特定欄位進行資料分析】
  • 6.
    6    第 5 行將row 陣列的「漲跌點數」欄位內容轉換為浮點數型態後判斷是否大於 9.34,若條件成立則將「漲跌點數」欄位內容輸出。 讀取出來的資料欄位名稱可以更進一步簡化為特定的代碼,「漲跌點數」欄位 是第 6 個欄位,若依照英文字母排列則是 f,請於 unbuntu 內請開啟 Spyder 編 輯 python 文件後執行(檔名為 csv-3.py): 01 02 03 04 05 06 07 08 09 # -*- coding: utf-8 -*- import csv f=open('example.csv',"r") for row in csv.DictReader(f,['a','b','c','d','e','f']): if float(row['f'])>71 : print(row['f']) else: print("error") f.closed 【圖 5、讀取 CSV 檔案後將欄位名稱簡化為特定代碼並做條件分析】 第 4 行建立一個迴圈,透過 csv.DictReader 逐行讀取 f 物件資料,讀取 f 物 件資料後依序放入規劃欄位名稱為 a、c、d、e、f 的 row 陣列內。第 5 行將 row 陣列的「f」欄位內容轉換為浮點數型態後判斷是否大於 71,若條件成立則將「f」 欄位內容輸出,若不成立則輸出「error」。 除了讀取資料,我們也可以寫入資料到 CSV 檔案內,寫入的方式有兩種,「a」 代表附加,若檔案存在則會在原有內容後附加上去;「w」代表覆蓋,若檔案存在 則會刪除原內容後添加新資料。請於 unbuntu 內請開啟 Spyder 編輯 python 文件 後執行(檔名為 csv-4a.py): 1 2 3 4 5 6 # -*- coding: utf-8 -*- import csv data=[['a','b',100,3.5],['x','y',200,7.5]] f=open("test2.csv","a") f.writerows(data) f.closed 請查看 test2.csv 檔案內容,另請修改第 4 行的"a"為"w",另存新檔(例如 csv-4b.py)後再執行,再請查看 test2.csv 檔案內容。
  • 7.
    7    儲存 CSV 檔案時也可挑選其他格式,請於unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 csv-5.py): 1 2 3 4 5 6 # -*- coding: utf-8 -*- import csv with open('eggs.csv','w') as csvfile: s=csv.writer(csvfile,delimiter='-',quotechar="|",quoting=csv.QUOTE_MINIMA L) s.writerow(['Spam1','Spam2','Spam3']) s.writerow(['Spam11','Spam21','Spam31']) 第 3 行進行檔案連結處理,以 w 寫入方式開啟 eggs.csv 檔案,第 4 行則要進 行寫入的格式設定。第 4 行有三個參數,如表 1 的說明。 參數 說明 delimiter 代表分隔符號 quotechar 代表包住字串的符號 quoting 插入到 CSV 文件中的一行記錄加入 quotechar 的方式 【表 1、儲存 CSV 檔案時挑選其他格式】 插入到 CSV 文件中的一行記錄加入 quotechar 的方式可參考表 2 的說明。 quoting 說明 csv.QUOTE_ALL 不論任何類型,全部都可以設定為符號。 csv.QUOTE_MINIMAL 使用特殊字元的欄位。 csv.QUOTE_NONNUMERIC 使用不是數字的欄位。 csv.QUOTE_NONE 不使用輸出的任何資料。 【表 2、插入到 CSV 文件中的一行記錄加入 quotechar 的方式】 特殊 csv 檔案格式內容如下: |Spam1|-|Spam2|-|Spam3| |Spam11|-|Spam21|-|Spam31| 三、 圖表顯示 進行圖表顯示之前,我們可利用終端機環境內互動的方式立即產生圖表,請於 終端機內啟動 ipython: ipython --pylab 接著請您輸入以下的資料: plot([1,2,3,2,3,2,2,1])
  • 8.
    8    您會看到這邊產生了一個圖表。 【圖 6、ipython 產生的圖表:y軸給值】 這圖表可以分為好幾個區域,在此略作說明如下: x and y axis:x 是水平的軸線、y 是垂直的軸線。 x and y tickers:代表 x 軸與 y 軸的刻度,這刻度代表坐標軸的分隔,包括最 小與最大的刻度。 x and y values:代表 x 軸與 y 軸的刻度內容 figure:畫布,圖表繪製於上。
  • 9.
    9    【圖 7、figure 畫面說明】 前面的資料只提供y 值,x 軸為默認值,因 plot()內參數有 7 個,所以 x 由 0 到 7 進行繪圖。現在嘗試加入 x 軸的值,我們來看看畫面會如何顯示。請於終端 機內啟動 ipython: ipython --pylab 接著請您輸入以下的資料: plot([3,4,6],[2,7,5])
  • 10.
    10    【圖 8、ipython 產生的圖表:x軸與 y 軸給值】 前面為 X 軸,後面為 Y 軸的方式給值。您也可以合併兩個數據後輸出,比如說 延續上個練習,接著請您輸入以下的資料: plot([9,8,7]) 【圖 9、ipython 產生兩個圖表】 畫面上將會出現兩個圖表資訊,所以您可使用 ipython 於終端機測試,再開始 寫程式。 1、 基本繪圖說明 我們試著在一個文件上繪製六個圖表,藉此了解各種基本繪圖指令。請於 unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 1.py): 01 02 03 04 05 06 07 # -*- coding: utf-8 -*- import matplotlib.pyplot as plt x = [1,2,3,4] y = [5,4,3,2] plt.figure() plt.subplot(231) plt.plot(x, y)
  • 11.
    11    08 09 10 11 12 13 14 15 16 17 18 19 20 plt.subplot(232) plt.bar(x, y) plt.subplot(233) plt.barh(x, y) plt.subplot(234) plt.bar(x,y) y1 = [7,8,5,3] plt.bar(x, y1, bottom=y, color = 'r') plt.subplot(235) plt.boxplot(x) plt.subplot(236) plt.scatter(x,y) plt.show() 【圖 10、切割成 6 等份顯示圖表】 這一張圖的資訊非常豐富,我們可以一張一張繪製,不過為了讓您了解 python 功能的強大,這邊選擇一次繪製六張圖表。
  • 12.
    12    透過 figure 動作可以建立一個畫布,於這畫布上可透過plot()做基本的繪圖, plot()可對x 座標及相對應的y 座標進行繪製。若於畫布上寫要繪製多張圖表, 可使用 subplot()這個動作,subplot()動作內可加入三個參數,我們以 mnp 來 表示,可以切割為 m 乘以 n 個區域,而 p 代表第幾個位置。接著各單元可簡介各 種圖表的規劃設計。 2、 長條圖 長條圖樣式將會使用 bar()這動作,bar()的參數樣式很多,可以使用 bar(X,Y) 代表 x 軸位置與 y 軸內容,或者可用 bar(X,Y,width)代表 x 軸位置與 y 軸內容 及寬度;bar (x, y1, bottom=y, color = 'r')代表 x 為 x 軸位置,y1 為 y 軸 內容,顏色為紅色,而「bottom=y」代表堆疊。橫向長條圖可用 barh()動作操 作,參數與 bar()相同,只是方向不同。 我們試著在一個文件上繪製長條圖,藉由數量的不同進行區間的調整。請於 unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 2.py): 1 2 3 4 5 6 7 8 9 # -*- coding: utf-8 -*- import matplotlib.pyplot as plt y = [3, 10, 7, 5, 3, 4.5, 6, 8.1] N = len(y) x = range(N) width = 1/1.5 plt.figure() plt.bar(x, y, width, color="blue") plt.show( )
  • 13.
    13    【圖 11、基本的長條圖】 接著我們對資料進行格式化動作,X 軸上出現說明文字,以及給予每一個座標 內容,我們規劃了三個長條圖,內容分別為26、17、30,X 軸上顯示 Label0、 Label1、Label2。請於 unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名 為 3.py): 1 2 3 4 5 6 7 # -*- coding: utf-8 -*- import matplotlib.pyplot as plt dictionary = plt.figure() D = {u'Label0':26, u'Label1': 17, u'Label2':30} plt.bar(range(len(D)), D.values(), align='center') plt.xticks(range(len(D)), D.keys()) plt.show( )
  • 14.
    14    【圖 12、設定標籤的長條圖】 接下來的設計就稍微複雜了,我們不僅將兩種資料合併在一個長條圖上,且設 定了 X軸與 Y 軸的刻度標籤。請於 unbuntu 內請開啟 Spyder 編輯 python 文件後 執行(檔名為 4.py): 01 02 03 04 05 06 07 08 09 10 11 12 # -*- coding: utf-8 -*- import matplotlib.pyplot as plt import numpy as np mpl_fig = plt.figure() ax = mpl_fig.add_subplot(111) N = 5 menMeans = (20, 35, 30, 35, 27) womenMeans = (25, 32, 34, 20, 25) menStd = (2, 3, 4, 1, 2) womenStd = (3, 5, 2, 3, 3) ind = np.arange(N) width = 0.35
  • 15.
    15    13 14 15 16 17 18 19 20 21 22 p1 = ax.bar(ind,menMeans, width, color=(0.2588,0.4433,1.0)) p2 = ax.bar(ind, womenMeans, width, color=(1.0,0.5,0.62), bottom=menMeans) ax.set_ylabel('Scores') ax.set_xlabel('Groups') ax.set_title('Scores by group and gender') ax.set_xticks(ind + width/2.) ax.set_yticks(np.arange(0, 81, 10)) ax.set_xticklabels(('G1', 'G2', 'G3', 'G4', 'G5')) plt.show( ) 【圖 13、設定刻度標籤的長條圖】 下一個練習我們就會將三組資料依據時間以不同顏色顯示。請於 unbuntu 內請 開啟 Spyder 編輯 python 文件後執行(檔名為 5.py): 01 02 03 # -*- coding: utf-8 -*- import matplotlib.pyplot as plt from matplotlib.dates import date2num
  • 16.
    16    04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 import datetime multiple_bars =plt.figure() x = [datetime.date(2016, 1, 4), datetime.date(2016, 1, 5), datetime.date(2016, 1, 6)] x = date2num(x) y = [4, 9, 2] z=[1,2,3] k=[11,12,13] ax = plt.subplot(111) ax.bar(x-0.2, y,width=0.2,color='b',align='center') ax.bar(x, z,width=0.2,color='g',align='center') ax.bar(x+0.2, k,width=0.2,color='r',align='center') ax.xaxis_date() plt.show() 【圖 14、依據時間分組的長條圖】 下一個練習我們將於 X 軸與 Y 軸加上標籤,並且於圖表文件上加上圖例說明文
  • 17.
    17    字。請於 unbuntu 內請開啟Spyder 編輯 python 文件後執行(檔名為 5a.py): 01 02 03 04 05 06 07 08 09 10 11 12 13 # -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt x = np.arange(0, 10, 1) y = np.log(x) xe = 0.1 * np.abs(np.random.randn(len(y))) plt.bar(x, y, yerr=xe, width=0.4, align='center', ecolor='r', color='cyan', label='experiment #1'); plt.xlabel('# measurement') plt.ylabel('Measured values') plt.title('Measurements') plt.legend(loc='upper left') plt.show() 【圖 15、加上圖例說明的長條圖】 3、 盒狀圖
  • 18.
    18    盒狀圖可用 boxplot( )規劃,盒狀圖的目的是顯示資料集合的整個範圍分布, 在一個盒狀圖內可以顯示出五種資訊。 1.最小值:資料集合中的最小值資料。 2. 第二四分位數:資料集合中較低的 25%資料。 3. 中間值:資料集合中位於 50%資料。 4. 第三四分位數:資料集合中的 75%資料。 5. 最大值:資料集合中的最大值資料。 我們將設計一個基本的盒狀圖。請於 unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 6.py): 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 # -*- coding: utf-8 -*- import matplotlib.pyplot as plt import numpy as np plt.figure() spread = np.random.rand(50) * 100 center = np.ones(25) * 50 flier_high = np.random.rand(10) * 100 + 100 flier_low = np.random.rand(10) * -100 data = np.concatenate((spread, center, flier_high, flier_low), 0) mpl_fig = plt.figure() ax = mpl_fig.add_subplot(111) ax.boxplot(data) ax.set_xlabel('Data Points') ax.set_ylabel('Variance') plt.show()
  • 19.
    19    【圖 16、基本的盒狀圖】 我們將設計多個盒狀圖,顯示隨機取數下資料的變化。請於 unbuntu內請開啟 Spyder 編輯 python 文件後執行(檔名為 7.py): 01 02 03 04 05 06 07 08 09 10 11 12 13 # -*- coding: utf-8 -*- import matplotlib.pyplot as plt import numpy as np plt.figure() N = 1000 data_set1 = np.random.normal(1, 1, N) data_set2 = np.random.lognormal(1, 1, N) data_set3 = np.random.exponential(1, N) data_set4 = np.random.gumbel(6, 4, N) data_set5 = np.random.triangular(2, 9, 11, N) data = [data_set1, data_set2, data_set3, data_set4, data_set5] mpl_fig = plt.figure() ax = mpl_fig.add_subplot(111)
  • 20.
  • 21.
    21    07 plt.show() 【圖 18、基本散佈圖】 接著我們藉由透明度的設計讓散佈圖有不一樣的變化,請於unbuntu 內請開啟 Spyder 編輯 python 文件後執行(檔名為 9.py): 01 02 03 04 05 06 07 08 09 10 # -*- coding: utf-8 -*- import matplotlib.pyplot as plt import numpy as np x = np.random.normal(size = 2000) y = np.random.normal(size = 2000) plt.scatter(x, y, alpha = 0.3) plt.title("scatterplot") plt.xlabel("x") plt.ylabel("y") plt.show()
  • 22.
    22    【圖 19、具透明度的散佈圖】 除了透明度的設計,我們也可以隨機方式改變散佈圖的大小,請於 unbuntu 內請開啟Spyder 編輯 python 文件後執行(檔名為 10.py): 01 02 03 04 05 06 07 08 # -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt x = np.random.rand(500) y = np.random.rand(500) z = np.random.normal(size = 500) plt.scatter(x, y, s = z * 200, alpha = 0.4) plt.show()
  • 23.
  • 24.
    24    屬性 類型 描述 alpha浮點數 Alpha值用來設置混色,並 不是所有項目都可以支持 color or c 任意 matplotlib 顏色 設置線條顏色. dashes 以點為單位的 on/off 序列 設置破折號序列,如果seq 為空或者seq = (None, None),那麼linestyle 將 會被設定為 solid. label 任意字串 為各種圖例說明所設定的 標籤 linestyle 或 ls [ '-' | '–' | '-.' | ':' | 'steps' | ...] 設定線條風格 (也可以接 受 drawstyles內容). linewidth 或 lw 以點為單位的浮點數型態數 值 設定以點為單位的線條寬 度. marker [ 7 | 4 | 5 | 6 | 'o' | 'D' | 'h' | 'H' | '_' | '' | 'None' | ' ' | None | '8' | 'p' | ',' | '+' | '.' | 's' | '*' | 'd' | 3 | 0 | 1 | 2 | '1' | '3' | '4' | '2' | 'v' | '<' | '>' | '^' | '|' | 'x' | '$...$' | tuple | Nx2 array ] 設定線條標記 markeredgecolor 或 mec 任何 matplotlib 顏色 設定標記的邊緣顏色 markeredgewidth或 mew 以點為單位的浮點數型態數 值 設定標記的邊緣寬度 markerfacecolor 或 mfc 任何 matplotlib 顏色 設定標記的顏色 markersize 或 ms 浮點數 設定以點為單位的標記大 小 solid_capstyle ['butt' | 'round' | 'projecting'] 設定實線的線端風格 solid_joinstyle ['miter' | 'round' | 設定實線的連接風格.
  • 25.
    25    'bevel'] visible [True |False] 顯示或隱藏 xdata np.array 設定x的np.array內容 ydata np.array 設定y的np.array內容 【表 3、線條屬性】 2、 線條風格與顏色 以下列表則是說明圖表中的線條風格: 線條風格 描述 線條風格 描述 '-' 實線 '-.' 點划線 '--' 破折線 ':' 虛線 'None', ' ', '' 甚麼都不畫 【表 4、線條風格】 以下列表則是說明圖表中的顏色 顏色 說明 顏色 說明 b 藍色 g 綠色 r 紅色 y 黃色 c 青色 k 黑色 m 洋紅色 w 白色 【表 5、顏色】 上述表格提供基本的顏色部分設定,若上述表格提供的顏色不符合需求,您可 以使用網頁的十六進位字串方式定義顏色,例如:color='#fe3465',就可以 做更複雜的顏色變化。