本文起意来自于某 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')
分享结束,欢迎大家交流想法!