顯示具有 Python 標籤的文章。 顯示所有文章
顯示具有 Python 標籤的文章。 顯示所有文章

2024年5月3日 星期五

VBA / Excel VBA將檔案另存成PDF再使用自訂python程式加密PDF 4

在前一篇 VBA / Excel VBA將檔案另存成PDF再使用自訂python程式加密PDF 3
曾經思考有沒有辦法不用先產生檔案的方式
轉了很多彎,後來看PyPDF2的說明
PdfWriter()的write()參數,可以是個路徑
:param stream: An object to write the file to. The object can support
   the write method and the tell method, similar to a file object, or
   be a file path, just like the fileobj, just named it stream to keep
   existing workflow.
這就代表不需要是實體檔案路徑
所以改寫程式碼如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import os, sys
from PyPDF2 import PdfReader 
from PyPDF2 import PdfWriter

def addPw(ar1, ar2):
    #print(ar1,ar2)
    pdf_path =ar1
    pswd=ar2
    
    #不含副檔名的檔案名稱
    fileName = os.path.basename(pdf_path).replace(".pdf", "")

    #最後輸出的檔案路徑  因為檔案加密之後 不能寫回原本的檔案   
    newFile = os.path.dirname(pdf_path)+"\\"+ fileName +"_pw.pdf"    
    
    #讀取原始檔案
    in_file = open(pdf_path, "r+b")
    in_pdf = PdfReader(in_file)
    
    #加密檔案
    out_pdf = PdfWriter()
    out_pdf.append_pages_from_reader(in_pdf)
    out_pdf.encrypt(pswd)
    
    #寫出檔案
    out_pdf.write(newFile)
    
    #關閉open()開啟的檔案
    in_file.close()

    #刪除PdfReader() PdfWriter()
    del in_pdf, out_pdf
    #print("檔案加密完成")
    
addPw(sys.argv[1], sys.argv[2])

#測試用
#addPw(r"D:\Google 雲端硬碟\莊生的箱子\網站_程式練習\VBA練習\PDF 轉檔 加密\output\臺北市.pdf","123456")
#addPw(r"D:\Google 雲端硬碟\莊生的箱子\網站_程式練習\python練習\創建PDF\output\臺北市.pdf","123456")
 

VBA / Excel VBA將檔案另存成PDF再使用自訂python程式加密PDF 3

再次修改 VBA / Excel VBA將檔案另存成PDF再使用自訂python程式加密PDF 的程式碼
1.使用 WScript.Shell 執行命令列、2.在迴圈增加 "DoEvents" 移交控制權
這次是修改python程式碼
原本的程式碼透過 shutil套件複製檔案2次
1個用來增加密碼
1個是用來寫入增加密碼的PDF
而原因是增加密碼的PDF無法寫回原檔案
後來覺得能否可以不用複製檔案??
目前的作法是用 fitz套件產生一個有一頁空白A4的實體PDF
然後用 PyPDF2套件的 pdfReader讀取原始檔
再用PyPDF2套件的 PdfWriter的append_pages_from_reader附加pdfReader
用encrypt增加密碼
最後再寫入空白A4的實體PDF
流程如下
#2 引入 fitz套件
備註:安裝套件要使用這個名稱「PyMuPDF」
#15-22 產生一個一頁A4空白頁的PDF
之後加密的流程大同小異
修改後的程式碼如下
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import os, sys
import fitz
from PyPDF2 import PdfReader 
from PyPDF2 import PdfWriter

def addPw(ar1, ar2):
    #print(ar1,ar2)
    pdf_path =ar1
    pswd=ar2
    
    #不含副檔名的檔案名稱
    fileName = os.path.basename(pdf_path).replace(".pdf", "")
    #print(fileName)
    
    #產生一個A4空白頁的PDF
    doc = fitz.open()
    #To add a blank page,
    w, h = fitz.paper_size("A4") 
    # -1, insertion point: end of document
    doc.new_page(-1, width = w, height = h)    
    newFile = os.path.dirname(pdf_path)+"\\"+ fileName +"_pw.pdf"
    doc.save(newFile)
    #print(newFile)
    
    #讀取檔案
    in_file = open(pdf_path, "r+b")
    in_pdf = PdfReader(in_file)
    
    #加密檔案
    out_pdf = PdfWriter()
    out_pdf.append_pages_from_reader(in_pdf)
    out_pdf.encrypt(pswd)
    
    #讀取用來存儲的檔案
    out_file = open(newFile, "wb")
    #寫出檔案
    out_pdf.write(out_file)
    
    #關閉open()開啟的檔案
    in_file.close()
    out_file.close()
    #刪除PdfReader() PdfWriter()
    del in_pdf, out_pdf
    #print("檔案加密完成")
    
addPw(sys.argv[1], sys.argv[2])

#測試用
#addPw(r"D:\Google 雲端硬碟\莊生的箱子\網站_程式練習\python練習\創建PDF\output\臺北市.pdf","123456")

2024年4月26日 星期五

VBA / Excel VBA將檔案另存成PDF再使用自訂python程式加密PDF

VBA能否將excel轉成加密的PDF?

這個是在Line的excel社團看到的提問

其中的管理員提供了一個網路教學

這個教學是使用 Adobe Acrobat 物件

但是前提是必須先安裝付費版的 Adobe Acrobat

我後來想起之前彰化一整天有分享某個客製程式

其中有PDF加密功能,這個功能是在VBA執行他自己寫的python程式

經過自己土炮測試之後

我的構想,整體流程可以分成三部分

第一部分是在Excel透過VBA將工作表另存成PDF

第二部分是透過python程式加密PDF

第三部分是在Excel VBA執行 python程式

1.在Excel透過VBA將工作表另存成PDF

這是透過Excel的內建功能將工作表複製到新的工作簿

然後再存成PDF

流程大致如下

透過迴圈,使用工作簿功能ExportAsFixedForma逐一將工作表轉成PDF

1
2
3
4
5
6
    For i = 2 To Sheets.Count
        nName = Sheets(i).Name
        Sheets(i).Copy
        ActiveWorkbook.ExportAsFixedFormat Type:=xlTypePDF, Filename:=outputFolderPath & nName & ".pdf"
        ActiveWorkbook.Close False
    Next

 

2.透過python程式加密PDF

這裡的知識點是如何讓python接收外部參數

最簡單的方式 透過sys.argv來接收從cmd傳入的參數

1
2
3
4
5
6
7
8
9
import sys

def getArg(ar1, ar2):
    
    print()
    print('接收參數:', ar1,ar2)
    print()

getArg(sys.argv[1], sys.argv[2])

 

將以上的程式碼存成xx.py (xx是指隨意名稱)

然後在cmd執行 python xx.py 1 2 

就會輸出

接收參數:1 2

另一個知識點是如何加密PDF

可以利用套件 PyPDF2來處理

流程如下

#6~43 自訂一個函數

#8 第一個參數為檔案路徑

#9 第二個參數為密碼

#12 取出不含副檔名的檔案名稱

os.path.basename(pdf_path) 可以取出檔案路徑中最後一層,也就是檔案名稱.副檔名

#15 設定暫存檔的完整路徑

#17 設定用來寫入的檔案路徑

os.path.dirname(pdf_path) 可以取出最後一層之外的路徑,也就是檔案所在的目錄

因為加密後的檔案無法寫回原檔案,所以寫入另一個pdf

#21-23 使用套件 shutil複製原檔案產生新檔案

#25-27 使用PyPDF2的PdfReader物件來讀取PDF

 要先用open讀取檔案,再用PdfReader讀取PDF

#29-32 加密PDF

使用PyPDF2的PdfWriter物件的append_pages_from_reader獲取從PdfReader讀取的PDF

再用encrypt來加密

#34-36 將加密後的檔案寫入到用來輸出的檔案

因為產生一個空白的PDF還需要用別的套件生成

感覺太麻煩...

所以直接複製原本的檔案

#38-39 關閉利用open開啟的檔案

#41 刪除暫存檔

#42 關閉 PyPDF2的PdfReader、PdfReader物件

#43 如果之後封裝的程式要在背景執行,就不能有任何的print寫出

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import os, sys
import shutil
from PyPDF2 import PdfReader 
from PyPDF2 import PdfWriter

def addPw(ar1, ar2):
    #print(ar1,ar2)
    pdf_path =ar1
    pswd=ar2
    
    #不含副檔名的檔案名稱
    fileName = os.path.basename(pdf_path).replace(".pdf", "")
    #print(fileName)
    #暫存檔 用來加密
    tempFile =os.path.dirname(pdf_path)+"\\"+ fileName + "_temp.pdf"
    #print(tempFile)
    #最後輸出的檔案  因為檔案加密之後 不能寫回原本的檔案
    newFile = os.path.dirname(pdf_path)+"\\"+ fileName +"_pw.pdf"
    #print(newFile)
    
    #複製產生檔案
    shutil.copyfile(pdf_path, tempFile)
    shutil.copyfile(pdf_path, newFile)
    
    #讀取暫存檔案
    in_file = open(tempFile, "r+b")
    in_pdf = PdfReader(in_file)
    
    #加密檔案
    out_pdf = PdfWriter()
    out_pdf.append_pages_from_reader(in_pdf)
    out_pdf.encrypt(pswd)
    
    #讀取用來存儲的檔案
    out_file = open(newFile, "wb")
    #寫出檔案
    out_pdf.write(out_file)
    
    #關閉open()開啟的檔案
    in_file.close()
    out_file.close()
    #刪除暫存檔
    os.remove(tempFile)
    #刪除PdfReader() PdfWriter()
    del in_pdf, out_pdf
    print("檔案加密完成")
    
addPw(sys.argv[1], sys.argv[2])

#addPw(r"C:\Users\edu\Desktop\PDF 轉檔 加密\output\臺北市.pdf","123456")

之後再用pyinstaller封裝成執行檔

3.在Excel VBA執行 python程式

#6-37 將工作表轉存成PDF

#39-51 讀取輸出資料夾內的所有PDF,將完整的檔案路徑寫入陣列中

#55-66 利用陣列進行迴圈

#59 是PDF密碼,之後可以再視需求來修改

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
Public Sub export_encrypt_PDF()

    Application.DisplayAlerts = False
    Application.ScreenUpdating = False
    
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    ActiveWorkbook.Sheets(1).Activate
    
    '目前檔案路徑
    nPath = ActiveWorkbook.Path
    '輸出資料夾名稱
    strFolderName = "output"
    
    '完整的輸出資料夾路徑
    outputFolderPath = nPath & Application.PathSeparator & strFolderName & Application.PathSeparator

    '判斷輸出資料夾是否存在
    strFolderExists = Dir(nPath & Application.PathSeparator & strFolderName, vbDirectory)
    
    If strFolderExists = "" Then
        '不存在則新增
        fso.CreateFolder nPath & Application.PathSeparator & strFolderName
    Else
        '存在則移除 再新增
        fso.DeleteFolder nPath & Application.PathSeparator & strFolderName, True 'True 強制刪除
        fso.CreateFolder nPath & Application.PathSeparator & strFolderName
    End If
    
    '將工作表轉存為PDF檔
    For i = 2 To Sheets.Count
        nName = Sheets(i).Name
        Sheets(i).Copy
        ActiveWorkbook.ExportAsFixedFormat Type:=xlTypePDF, Filename:=outputFolderPath & nName & ".pdf"
        ActiveWorkbook.Close False
    Next
    
    '讀取output資料夾的PDF 如果存在 回傳檔案名稱.副檔名
    pdfFile = Dir(outputFolderPath & "*.pdf")
        
    Dim fileArr() As String
    i = 0
    Do While pdfFile <> ""
        ReDim Preserve fileArr(i)
        fileArr(i) = outputFolderPath & pdfFile
        'Debug.Print outputFolderPath & pdfFile
        
        i = i + 1
        pdfFile = Dir()
    Loop
        
    'Debug.Print fileArr(0)
    '陣列上限(序位值)
    num = UBound(fileArr)
    
    For i = 0 To num
        sourceFilename = fileArr(i)
        setPassword = "123456"
        
        '透過cmd 執行pdf加密程式
        s = Chr(34) & Excel.ActiveWorkbook.Path & "\" & "0426_3.exe" & Chr(34) & Chr(32) & Chr(34) & sourceFilename & Chr(34) & Chr(32) & Chr(34) & setPassword & Chr(34)
            
        'Debug.Print s
        Shell s
    Next
    
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
End Sub

 

參考資料

如何用pyinstaller将需要传参数的Python文件生成exe文件

Python:批次加密PDF文件

别再问我怎么Python打包成exe了!

2024年4月14日 星期日

Py / 透過selenium-webdriver爬youtube的介紹資訊 2

在 Py / 透過selenium-webdriver爬youtube的介紹資訊(2021/10/28修改)

所引用的selenium-webdriver 在更新之後,目前selenium版本是4.19.0

可以不用設置driver.exe的路徑,selenium可以處理瀏覽器和驅動程序

抓取網頁元素的方式也有改變

更新之後的程式碼如下

 
  1. from selenium import webdriver
  2. # 2024.04.03 更新為 4.19.0 許多方法變動
  3. import time
  4. #
  5. #目前使用的selenium版本是4.19.0,可以不必设置driver.exe的路径,selenium可以自己处理浏览器和驱动程序
  6. #chromedriver.exe執行檔所存在的路徑 須配合電腦上的chrome版本
  7. #chrome_path =r"C:\Users\trico\Desktop\chromedriver\chromedriver.exe"
  8. #chrome_path =r"D:\chromedriver_win32\chromedriver.exe"
  9. options = webdriver.ChromeOptions() #透過options紀錄webdriver.ChromeOptions()的設定
  10. options.add_argument("--headless") #增加啟動參數,瀏覽器頁面不可視化(背景執行)
  11. browser = webdriver.Chrome(options)
  12.  
  13. #讀取資料
  14. f = open("url.csv","r")
  15. s = f.readlines()
  16. c = "科目,示例名稱,網址,介紹\n" #設定寫出檔案的第一行
  17. for i in range(1,len(s)):
  18. url=s[i]
  19. list=url.split(",") #分割串列
  20. # print(list[2].replace('\n','')) #第3筆是最後1筆資料會有換行符號,須去掉
  21. browser.get(list[2].replace('\n','')) #載入網址
  22. time.sleep(3) #等待3秒載入網頁
  23. #tagX = browser.find_element_by_xpath("//meta[@name='description']") # meta標籤 name屬性值為'description'的元素
  24. #新的方法
  25. tagX = browser.find_element("xpath","//meta[@name='description']")
  26. #tag = browser.find_element_by_id('description') #資訊所在的DIV id 現在不能直接抓Html
  27. #print(tagX.get_attribute("content")) #取出其中的content屬性值
  28. tag = tagX.get_attribute("content")
  29. tag2 = tag.replace('\n','').replace('\r','') #用空字串取代所有換行符號 ,不能用strip刪除
  30. #tag2=tag.text.replace('\n','').replace('\r','') #用空字串取代所有換行符號 ,不能用strip刪除
  31. # print(tag2)
  32. # print(len(tag2))
  33. # 因為沒有資訊也同樣能抓到空字串,不會出現錯誤
  34. # try:
  35. # tag = browser.find_element_by_id('description')
  36. # tag2=tag.text.replace('\n', '').replace('\r', '')
  37. # c +="{},{},{},{}".format(list[0],list[1],list[2],tag2)
  38. # print(c)
  39. # except:
  40. # c +="{},{},{},{}".format(list[0],list[1],list[2],"無說明")
  41. # continue
  42. # print(c)
  43. # 改用 if判斷 len(tag2)是否>0
  44. if i < len(s)-1: #如果不是最後一筆才加分行符號
  45. if len(tag2) > 0 :
  46. print(tag2)
  47. c +="{},{},{},{}\n".format(list[0],list[1],list[2].replace('\n',''),tag2)
  48. else:
  49. tag2="無內容資訊"
  50. c +="{},{},{},{}\n".format(list[0],list[1],list[2].replace('\n',''),tag2)
  51. print(tag2)
  52. else:
  53. if len(tag2) > 0 :
  54. print(tag2)
  55. c +="{},{},{},{}".format(list[0],list[1],list[2].replace('\n',''),tag2)
  56. else:
  57. tag2="無內容資訊"
  58. c +="{},{},{},{}".format(list[0],list[1],list[2].replace('\n',''),tag2)
  59. print(tag2)
  60. #寫出資料
  61. fw=open("c.txt","w",encoding="utf8")
  62. fw.write(c)
  63. fw.close()
  64. print(c)
  65. browser.close() #關閉 瀏覽器
  66. print("完成")

 

如果引用from selenium.webdriver.common.by import By

tagX = browser.find_element("xpath","//meta[@name='description']")

就要改成

tagX = browser.find_element(By.xpath,"//meta[@name='description']")

參考資料

爬虫学习记录(持续更新) 

selenium 4.19.0 

selenium入门超详细教程——网页自动化操作

2022年10月13日 星期四

Py / Python網頁資料擷取與分析班-筆記 10/11

主要內容

_303題果菜批發市場拍賣行情
_305題登革熱病例統計用groupby群組與統計
_401題資料折線圖繪製說明
_403題長條圖與圓餅圖與複合圖
_405題樣本:直方圖與散佈圖


1.303題果菜批發市場拍賣行情

直接在程式裡建構資料

選取、修改資料的方式比較簡單,等於是依據變數資料型態來使用對應的方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 303果菜批發市場拍賣行情

# 載入 pandas 模組縮寫為 pd
import pandas as pd
# 建構資料
datas = [[9, 203674, 13.2, 18894],
         [11.7, 180785, 12.3, 54894],
         [10.1, 127802, 14.7, 18563],
         [11.8, 28604, 14.9, 21963],
         [13.2, 600, 13.1, 900],
         [6.9, 38071, 9.6, 3555],
         [12.1, 35660, 10.6, 9005],
         [12, 15000, 13, 12000],
         [11.7, 48770, 9.1, 14370],
         [9.84, 6100, 11.89, 8980]]
indexs = ["三重市", "台中市", "台北一", "台北二", "台東市", "板橋區", "高雄市", "嘉義市", "鳳山區", "豐原區"]
columns = ["西瓜價", "西瓜量", "香瓜價", "香瓜量"]
# 輸出如拍賣行情價量表
df = pd.DataFrame(datas, columns=columns,  index=indexs)

print('西瓜與香瓜之拍賣行情價量表')
print(df)
print()  # 使用print分隔

# 以西瓜價遞減排序後,輸出各市場的西瓜價
df1 = df.sort_values(by="西瓜價", ascending=False)
print('以西瓜價遞減排序')
print(df1['西瓜價'])
print()  # 使用print分隔

# 計算台北一市場西瓜/香瓜價量的行情並輸出
df.loc["台北一"]
print('台北一市場的行情')
print(df.loc["台北一"])
print()  # 使用print分隔

# 將「三重市」改為「三重區」
indexs[0] = "三重區"
#「香瓜價」改為「洋香瓜價」
columns[2] = "洋香瓜價"
#「香瓜量」改為「洋香瓜量」
columns[3] = "洋香瓜量"
# 重新輸出整個表格
df.index = indexs
df.columns = columns

print('全體市場行情')
print(df)

 

如果是讀取本機資料的話,要指定哪一個欄位為index

選取資料的方式跟從程式建構資料的方式一樣

最大的差別是修改資料

如果是修改column

df.rename(columns={“香瓜價”:“洋香瓜價”,“香瓜量”:“洋香瓜量”}, inplace=True)

如果是修改index

df.rename(index={“三重市”:“三重區”}, inplace=True)

如果要修改資料的話

可以使用iloc( )定位之後直接修改

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 303果菜批發市場拍賣行情

# 載入 pandas 模組縮寫為 pd
import pandas as pd

# 讀取本機檔案 並以"市場名稱"欄位為index
df = pd.read_csv("read303.csv", index_col="市場名稱",encoding="cp950")
print(df)

print('西瓜與香瓜之拍賣行情價量表')
print(df)
print()  # 使用print分隔
# 
# 以西瓜價遞減排序後,輸出各市場的西瓜價
df1 = df.sort_values(by="西瓜價", ascending=False)
print('以西瓜價遞減排序')
print(df1['西瓜價'])
print()  # 使用print分隔

# 計算台北一市場西瓜/香瓜價量的行情並輸出
df.loc["台北一"]
print('台北一市場的行情')
print(df.loc["台北一"])
print()  # 使用print分隔
# 
# 將「三重市」改為「三重區」
# 「香瓜價」改為「洋香瓜價」
# 「香瓜量」改為「洋香瓜量」

df.rename(index={"三重市":"三重區"}, inplace=True)
print(df.index)

df.rename(columns={"香瓜價":"洋香瓜價","香瓜量":"洋香瓜量"}, inplace=True)
print(df.columns)

print()  # 使用print分隔
print('全體市場行情')
print(df)

 

2.305題登革熱病例統計用groupby群組與統計

老師的範例是Python 3擷取與分析證照考試的標準答案

居住縣市病例人數,並按遞減順序顯示

df_county = df1.groupby(“居住縣市”)[“居住縣市”].count()

df_county.sort_values(ascending=False)

其實可以合併成

df1.groupby(“居住縣市”)[“居住縣市”].count().sort_values(ascending=False)

使用groupby()分群再取出”居住縣市”以count( )計數,最後再用sort_values( )排序

也等於df1.groupby(“居住縣市”).居住縣市.count().sort_values(ascending=False)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 305登革熱病例統計

# 載入 pandas 模組縮寫為 pd
import pandas as pd
# 讀取csv檔
#df1 = pd.read_csv('read305.csv', encoding="utf-8", sep=",", header=0)
df1 = pd.read_csv('read305.csv', encoding="utf-8")
# 居住縣市病例人數,並按遞減順序顯示
df_county = df1.groupby("居住縣市")["居住縣市"].count()
#print(df_county)
print(df_county.sort_values(ascending=False))
# 顯示感染病例人數最多的5個國家,並按遞減順序顯示
df_country = df1.groupby("感染國家")["感染國家"].count()
print(df_country.sort_values(ascending=False).head(5))
# 台北市各區病例人數
df_taipei = df1[df1.居住縣市 == "台北市"]
print(df_taipei.groupby("居住鄉鎮")["居住鄉鎮"].count())
# 台北市最近病例的日期
print("發病日: " + df_taipei.發病日.max())

 

我嘗試用其他的方法來達成相同的效果

居住縣市病例人數,並按遞減順序顯示

df1.groupby(“居住縣市”).size().sort_values(ascending=False)

使用size( )取得”居住縣市”各分群的大小(數量),再用sort_values( )排序

台北市各區病例人數

先將整體資料以”居住縣市”分群,取得分群中的”台北市”,再用”居住鄉鎮”進一步分群,然後用size( )取得各分群的大小(數量)

台北市最近病例的日期

也是先將整體資料以”居住縣市”分群,取得分群中的”台北市”,然後以max( )取得”發病日”的最大值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 305登革熱病例統計

# 載入 pandas 模組縮寫為 pd
import pandas as pd
# 讀取csv檔
#df1 = pd.read_csv('read305.csv', encoding="utf-8", sep=",", header=0)
df1 = pd.read_csv('read305.csv', encoding="utf-8")
# 居住縣市病例人數,並按遞減順序顯示
print("居住縣市病例人數,並按遞減順序顯示")
print()

print(df1.groupby("居住縣市").size())
print(df1.groupby("居住縣市").size().sort_values(ascending=False))

# # 顯示感染病例人數最多的5個國家,並按遞減順序顯示
print()
print("顯示感染病例人數最多的5個國家,並按遞減順序顯示")
print(df1.groupby("感染國家").size().sort_values(ascending=False).head(5))

df_county = df1.groupby("居住縣市")
# # 台北市各區病例人數
print()
print("台北市各區病例人數")
print(df_county.get_group("台北市").groupby("居住鄉鎮").size())

# # 台北市最近病例的日期
print()
print("台北市最近病例的日期")
print(df_county.get_group("台北市").發病日.max())
print(df_county.get_group("台北市")["發病日"].max())

 

3.401題資料折線圖繪製說明

plt.plot的參數基本設定(x, y),至少需要有X軸數值以及Y軸數值

比較需要注意的是設定字體的方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#401資料:折線圖
import matplotlib.font_manager as fm
import matplotlib.pyplot as plt

# 設定字體的檔案位置,並放到fm.FontProperties裡
fontPath = r"C:\Windows\Fonts\msjh.ttc"
fontConfig = fm.FontProperties(fname=fontPath, size=18)

data1 = [1, 4, 9, 16, 25, 36, 49, 64]
data2 = [1, 2, 3, 6, 9, 15, 24, 39]
seq=range(1,len(data1)+1)
plt.plot(seq, data1, 'bo--', seq, data2, 'ro--', linewidth=2)
plt.axis([0, 8, 0, 70])
plt.title("折線圖", fontproperties=fontConfig)
plt.xlabel("x軸", fontproperties=fontConfig)
plt.ylabel("y軸", fontproperties=fontConfig)
plt.show()
# 輸出圖片檔案
# plt.savefig('chart.png')
#plt.close()

 

4.403題長條圖與圓餅圖與複合圖

利用plt.subplot(nrows, ncols, index )來設定複合圖的呈現方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#403月份統計:長條圖與圓餅圖
# 載入 matplotlib.pyplot 並縮寫為 plt
import matplotlib.pyplot as plt
# 四個月份
labels = ["Jun", "Jul", "Aug", "Sep"]
sizes = [20, 30, 40, 10]
# 圓餅圖顏色
colors = ["yellowgreen", "gold", "lightskyblue", "lightcoral"]

# 長條圖 位置
plt.subplot(1, 2, 1)
xticks = range(1, len(labels) + 1)
# 長條圖以labels為X軸,sizes為Y軸,各長條顏色為藍色(blue)
plt.xticks(xticks, labels)
plt.bar(xticks, sizes, color="blue")

# 圓餅圖 位置
plt.subplot(1, 2, 2)
# 圓餅圖以labels為圖標,sizes為各項所占百分比
# 圓餅圖colors為各項顏色,突顯「Aug」
# 圓餅圖顯示各項百分比到小數點第1位
explode = [0, 0, 0.1, 0]
plt.pie(sizes, explode=explode, labels=labels,
        colors=colors, autopct="%1.1f%%")
# 長寬比為1:1
# plt.axis("equal")
# plt.savefig("chart.png")
# plt.close()
plt.show()

 

5.405樣本:直方圖與散佈圖

使用numpy套件來產生數值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#405樣本:直方圖與散佈圖
# 在 import matplotlib.pyplot as plt 之前執行執行 mpl.use("Agg")
# 將不會顯示圖示 即使 plt.show()
# 如果要恢復
# 需要執行 # mpl.use("TKAgg")
# =============================================================================
# import matplotlib as mpl
# mpl.use("Agg")
# =============================================================================

# np.random.RandomState()的隨機值
# 如果為 None 每次都會產生不同的隨機值
# 如果是一個固定數值  每次都會產生相同的隨機值
set_seed = 123
import numpy as np
import matplotlib.pyplot as plt

#從常態分布(平均數1 標準差0.5)中隨機抽取1000個數值
samples_1 = np.random.RandomState(set_seed).normal(loc=1, scale=0.5, size=1000)

#從df自由度的標準Student t分布中隨機抽取1000個數值。
samples_2 = np.random.RandomState(set_seed).standard_t(df=10, size=1000)

#print(samples_1)
# print(samples_2)

#產生介於-3 3之間均勻等差數列 數據量為100個
bins = np.linspace(-3, 3, 100)
# print(bins)

# 第一個子圖 直方圖(histogram)
plt.subplot(2, 2, 1)
plt.hist(samples_1, bins=bins, alpha=0.5, label="samples 1")
plt.hist(samples_2, bins=bins, alpha=0.5, label="samples 2")
# 在左上角 upper left 放置圖例 legend
plt.legend(loc="upper left")

# 第二個子圖 散佈圖(scatter)
plt.subplot(1, 2, 2)
plt.scatter(samples_1, samples_2, alpha=0.2)

plt.show()
# plt.savefig("chart.png")
# plt.close()

 

參考資料:

由 Pandas 的 DataFrame 中取得資料
[Day10]Pandas Groupby使用!
numpy.random.RandomState
Python 繪製折線圖 Plot Line Charts
matplotlib.pyplot.subplot
Matplotlib 饼图
py数分笔记(3):np.random.seed()与np.random.RandomState()
【Python】np.linspace用法介紹
掌握了Matplotlib這兩個方法,輕鬆繪製出漂亮的直方圖!
Python matplotlib.pyplot.scatter()用法及代碼示例
matplotlib.use(‘agg’)的作用
解决 Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure