本文起意來自于某 Python 考證班的一道考試題,題目要求使用 import csv 導入子產品,對10年間的中國行政區劃個數進行對比,編者将采用3種方法進行解題。其中,前2種方法按考題要求使用了 csv 子產品功能,并且不可再導入其他子產品;第3種方法,作為一種探讨,沒有調用 csv 子產品,也實作了相關功能。現做如下分享:
資料來源:
從國家統計局官網 https://data.stats.gov.cn/easyquery.htm?cn=C01 查詢近10年中國行政區劃資料,如下圖:

感興趣讀者可以直接打開網頁複制相關資料,建立 excel 表格,粘貼并删除第9行以下資料,将【年】替除,另存為【中國行政區劃個數.csv】檔案,即可運作後邊分享的程式。
程式設計目标:
以2012年為基準資料,能直覺檢視10年資料變化情況:
1)讀取【中國行政區劃個數.csv】檔案得到原始資料,内容如下圖:
2)将2013年至2021所有年份的數值都減去2012年對應的數值;
3)将核減後的新資料存到【中國行政區劃個數對比2012年增減情況.csv】新檔案中,存儲内容如下圖:
程式分享:
import csv
filename_in = './中國行政區劃個數.csv'
filename_out1 = './中國行政區劃個數對比2012年增減情況_DictReader.csv'
filename_out2 = './中國行政區劃個數對比2012年增減情況_reader.csv'
filename_out3 = './中國行政區劃個數對比2012年增減情況_str.csv'
#【方法一】
# 調用 csv 子產品中 DictReader 類的方法讀取 csv 檔案的對象,生成資料字典,減值計算修改指派,
# 最後,調用 csv 子產品中 DictWriter 類的方法将字典資料寫入指定的檔案中
# 步驟一:讀取原始資料,形成資料字典 csv_data
with open(filename_in, 'r', encoding='utf-8') as csvfile:
# DictReader 類用 csv 檔案第1行作為字典 key 屬性名,并傳回一個能周遊 csv 檔案
# 所有行的 csv.DictReader(字典對象) csv_r
csv_r = csv.DictReader(csvfile)
csv_data ={} # 初始化 csv 資料字典
key = 0 # 初始化 csv 資料字典鍵名
for row in csv_r: # 周遊 csv 字典對象 csv_r 生成 collections.OrderedDict(采集有序字典) row
key += 1 # 數值累加生成新鍵名
dict ={} # 初始化【行字典】
# 利用 items()函數,以清單傳回可周遊的(鍵,值)元組數組
for k,v in row.items(): # 周遊 collections.OrderedDict 采集有序字典
if k != '名額': # 若為非【名額】列,将數值轉化為整數指派 K 鍵的行字典,用于下一步計算
dict[k] = int(v)
else:
dict[k] = v # 否則将【名額】列直接指派 K 鍵的行字典
csv_data[key] = dict # 将【行字典】指派給 key 鍵值的 csv_data字典
# 利用 items()函數,以清單傳回可周遊的(鍵,值)元組數組,計算2013-2021年數量 減2012的內插補點
for k,v in csv_data.items():
v0 = v['2012'] # 将 2012年數量指派 V0,用于以下2行程式使用
for y in range(2012,2022):
v[str(y)] -= v0
# 步驟二:将資料字典 csv_data 按步驟寫入指定的檔案
fieldname=['名額'] + [str(y) for y in range(2021,2011,-1)] # 利用 for 三元表達式組合生成表頭内容
# 以隻寫模式打開指定的檔案,若不存在則建立,若存在則覆寫。為避免空行顯示,設定參數:newline=''
with open(filename_out1, 'w', encoding='utf-8',newline='') as f:
# 調用 csv 子產品中類 DictWriter 方法得到 writer 對象
writer = csv.DictWriter(f,fieldnames=fieldname)
# 用 writer 對象調用 writeheader() 構造方法,将 fieldnames 參數寫入 csv檔案第一行或稱列标題、表頭
writer.writeheader()
#調用 writerows() 方法将修改的資料字典的鍵值寫進 csv 檔案中
for k,v in csv_data.items():
writer.writerow(v)
#【方法二】
# 調用 csv 子產品中 reader 類的方法按行讀取 csv 檔案的疊代對象
# 調用 open() 函數打開指定檔案,擷取 csvfile 檔案對象
csvfile = open(filename_in, 'r', encoding='utf-8')
# 用 csv.reader() 方法傳遞 csvfile 檔案對象參數,建立可周遊的 csv.reader 類型疊代對象
csv_r = csv.reader(csvfile)
n = 0 # 初始化表頭判斷參數
for row in csv_r: #周遊疊代對象 csv_r, 生成 row 清單資料
if n == 0: # 為表頭第一行,
# 以隻寫模式打開指定的檔案,若不存在則建立,若存在則覆寫。為避免空行顯示,設定參數:newline=''
with open(filename_out2,'w',encoding='utf-8',newline='') as f:
# 将 row 行清單資料轉換為字元串、替換掉多餘字元,行尾加換行符 \n,寫入檔案
f.write(str(row).replace("'",'').replace("[",'').replace("]",'')+'\n')
n = 1 # 完成表頭添加後,将判斷參數置1
else:
m = 0 # 初始化行清單位置參數
for v in row[::-1]: # 周遊反序行清單,進行內插補點計算并指派
if m == 0 : # 若 m == 0, 進入計算程式,為下一步計算做準備
v0 = int(v) # 将2012年字元串資料轉換為整數型資料指派v0,
m -= 1 # 随周遊将行清單位置參數減1
if m != -11: # 如果 m != -11 判斷為非【名額】字段,
row[m] = int(v)-v0 # 執行 int(v)-v0 內插補點指派計算
# 以 'a' 追加模式打開指定的檔案
with open(filename_out2,'a',encoding='utf-8',newline='') as f:
# 将 row 行清單資料轉換為字元串、替換掉'[]多餘字元,行尾加換行符 \n,寫入檔案
f.write(str(row).replace("'",'').replace("[",'').replace("]",'')+'\n')
#【方法三】
# 不調用 csv 子產品,用 file 檔案對象 readlines() 函數的方法按行讀取 file 檔案的疊代對象
# 調用 open() 函數打開指定檔案,擷取 file 檔案對象
file = open(filename_in, 'r', encoding='utf-8')
lines = file.readlines() # 利用 readlines() 按行讀取整個檔案内容并放到 lines 清單中
n = 0 # 初始化表頭判斷參數
for row in lines: #周遊行資料清單
row = row.replace('\n','') # 去每行資料除行尾的 \n
if n == 0: # 為表頭第一行,
# 以隻寫模式打開指定的檔案,若不存在則建立,若存在則覆寫。為避免空行顯示,設定參數:newline=''
with open(filename_out3,'w',encoding='utf-8',newline='') as f:
f.write(str(row)+'\n') # 将 row 第一行資料轉換為字元串,行尾加換行符 \n,寫入檔案
n = 1 # 完成表頭添加後,将判斷參數置1
else:
m = 0 # 初始化行清單位置參數
list = row.split(',') # 将字元串型的每行資料轉換為行清單資料
for v in list[::-1]: # 周遊反序行清單,進行內插補點計算并指派
if m == 0 : # 若 m == 0, 進入計算程式,為下一步計算做準備
v0 = int(v) # 将2012年字元串資料轉換為整數型資料指派v0,
m -= 1 # 随周遊将行清單位置參數減1
if m != -11: # 如果 m != -11 判斷為非【名額】字段,
list[m] = int(v)-v0 # 執行 int(v)-v0 內插補點指派計算
# 以 'a' 追加模式打開指定的檔案
with open(filename_out3,'a',encoding='utf-8',newline='') as f:
# 将 list 行清單資料轉換為字元串、替換掉'[]多餘字元,行尾加換行符 \n,寫入檔案
f.write(str(list).replace("'",'').replace("[",'').replace("]",'')+'\n')
分享結束,歡迎大家交流想法!