【商务合作联系qq】:1286257618
【技术交流群】:991807590
一、思路分析
耕地质量变更调查表的审查是为了确保原始数据的可靠性。主要检测《耕地质量等级》中十六个评价指标是否有空值,6个数值指标是否在《农业农村部耕地质量监测保护中心关于印发《全国耕地质量等级评价指标体系》的通知》规定的范围之内。该部分代码以面向对象编程的思路进行编写。主要分为三部分:
1. 构造函数,生成pandas.dataframe,以及传入县名称
2. check_na 函数检测十六个指标是否存在空值
3. check_over_bound 函数检测6个指标时候在标准规定的范围之内
二、代码实现
1. 构造函数
WORK_BASE_DIR和OUTPUT_BASE_DIR分别是耕地质量变更调查表的存放目录和检测结果的输出结果。
BORDER_DICT是县所属两级划分农业区中各农业区六种指标的下界和上界
self.df是pandas读取excel数据生成的DataFrame
self.county_name是通过正则表达式匹配文件名中的中文字符,也就是县名。
notes: r'[\u4e00-\u9fa5]*', [\u4e00-\u9fa5]表示任意中文字符,*表示任意多个字符
class OriginalCheck:
WORK_BASE_DIR = r'D:\课题组项目\2021耕地质量更新\1.耕地质量变更调查表'
OUTPUT_BASE_DIR = r'D:\课题组项目\2021耕地质量更新\2.耕地质量变更调查表_检测结果'
BORDER_DICT = {
'有效土层厚': [4.9999999999999999, 113.0000000000000001],
'土壤容重': [0.499999999999999999, 2.370000000000000001],
'pH': [2.9999999999999999999999, 9.5000000000000000001],
'有机质': [0.999999999999999999, 37.5000000000000000001],
'速效钾': [4.999999999999999999, 205.000000000000000001],
'有效磷': [0.099999999999999999, 252.300000000000000001]
}
def __init__(self, county_file):
self.df = pd.read_excel(OriginalCheck.WORK_BASE_DIR + '\\' + county_file)
self.county_name = re.match(r'[\u4e00-\u9fa5]*', county_file).group()
2. check_na 函数
步骤:
1. 对dataframe进行空值检测,生成空值字典
2. 将空值字典的数据组织为文本形式
3. 将文本数据写入检测结果txt文件
notes: f-string的特性请自行百度
def check_na(self):
# 1. 对dataframe进行空值检测,生成空值字典
nan_dict = {}
for i in range(len(self.df)):
for field in ['经度', '纬度', '地形部位', '耕层质地', '质地构型', '生物多样性', '障碍因素', '灌溉能力', '排水能力',
'农田林网化', '海拔高度', '有效土层厚', '土壤容重', 'pH', '有机质', '有效磷', '速效钾']:
# 如果遍历到的数据为空值,则该数据以{'固定编号': '指标'}的格式保存到nan_dict中
if pd.isna(self.df.loc[i, field]):
nan_dict[self.df.loc[i, '固定编号']] = field
self.df.loc[i, field] = 0 # 将空值赋0,以便进行越界检测
# 2. 将空值字典的数据组织为文本形式
check_result = ''
if nan_dict:
for i, (key, field) in enumerate(nan_dict.items(), 1):
check_result += f'{i}. 固定编号为【{key}】 的 【{field}】指标为空值\n'
else:
check_result = '无\n'
# 3. 将检测结果输出到txt
f = open(OriginalCheck.OUTPUT_BASE_DIR + '\\' + self.county_name + '原始数据检测结果.txt', 'w')
f.write(f'【{self.county_name}原始数据检测结果】\n'.center(150))
f.write('\n以下为空值判断结果:\n')
f.write(check_result)
f.close()
3. check_over_bound 函数
步骤:
1. 对dataframe进行越界检测,生成越界字典
2. 将越界字典的数据组织为文本形式
3. 将文本数据写入检测结果txt文件
def check_over_bound(self):
# 1. 越界判断
over_dict = {}
for i in range(len(self.df)):
for field in ['有效土层厚', '土壤容重', 'pH', '有机质', '有效磷', '速效钾']:
if self.df.loc[i, field] < OriginalCheck.BORDER_DICT.get(field)[0]:
# 越界字典的保存格式为{'固定编号': ['指标', '界限及界限值', '值']}
over_dict[self.df.loc[i, '固定编号']] = [field, f'下界{OriginalCheck.BORDER_DICT.get(field)[0]}',
self.df.loc[i, field]]
if self.df.loc[i, field] > OriginalCheck.BORDER_DICT.get(field)[1]:
over_dict[self.df.loc[i, '固定编号']] = [field, f'上界{OriginalCheck.BORDER_DICT.get(field)[1]}',
self.df.loc[i, field]]
# 2. 组织数据
check_result = ''
if over_dict:
for i, (key, [field, border, value]) in enumerate(over_dict.items(), 1): # enumerate(xxx, 1)表示从1开始编号
check_result += f'{i}. 固定编号为【{key}】 的 【{field}】指标越过了【{border}】,其值为【{value}】.\n'
else:
check_result = '无\n'
# 3. 将检测结果输出到txt
# 注意: open(path, 'a')以‘a’格式打开文件,表示文件不存在则创建文件,存在则追加到末尾。如果用‘w'模式打开则会覆盖前文空值检测的结果
f = open(OriginalCheck.OUTPUT_BASE_DIR + '\\' + self.county_name + '原始数据检测结果.txt', 'a')
f.write('\n以下为越界判断结果:\n')
f.write(check_result)
f.close()
三、完整代码
import os
import re
import pandas as pd
class OriginalCheck:
WORK_BASE_DIR = r'D:\课题组项目\2021耕地质量更新\1.耕地质量变更调查表'
OUTPUT_BASE_DIR = r'D:\课题组项目\2021耕地质量更新\2.耕地质量变更调查表_检测结果'
BORDER_DICT = {
'有效土层厚': [4.9999999999999999, 113.0000000000000001],
'土壤容重': [0.499999999999999999, 2.370000000000000001],
'pH': [2.9999999999999999999999, 9.5000000000000000001],
'有机质': [0.999999999999999999, 37.5000000000000000001],
'速效钾': [4.999999999999999999, 205.000000000000000001],
'有效磷': [0.099999999999999999, 252.300000000000000001]
}
def __init__(self, county_file):
self.df = pd.read_excel(OriginalCheck.WORK_BASE_DIR + '\\' + county_file)
self.county_name = re.match(r'[\u4e00-\u9fa5]*', county_file).group()
def check_na(self):
# 1. 对dataframe进行空值检测,生成空值字典
nan_dict = {}
for i in range(len(self.df)):
for field in ['经度', '纬度', '地形部位', '耕层质地', '质地构型', '生物多样性', '障碍因素', '灌溉能力', '排水能力',
'农田林网化', '海拔高度', '有效土层厚', '土壤容重', 'pH', '有机质', '有效磷', '速效钾']:
# 如果遍历到的数据为空值,则该数据以{'固定编号': '指标'}的格式保存到nan_dict中
if pd.isna(self.df.loc[i, field]):
nan_dict[self.df.loc[i, '固定编号']] = field
self.df.loc[i, field] = 0 # 将空值赋0,以便进行越界检测
# 2. 将空值字典的数据组织为文本形式
check_result = ''
if nan_dict:
for i, (key, field) in enumerate(nan_dict.items(), 1):
check_result += f'{i}. 固定编号为【{key}】 的 【{field}】指标为空值\n'
else:
check_result = '无\n'
# 3. 将检测结果输出到txt
f = open(OriginalCheck.OUTPUT_BASE_DIR + '\\' + self.county_name + '原始数据检测结果.txt', 'w')
f.write(f'【{self.county_name}原始数据检测结果】\n'.center(150))
f.write('\n以下为空值判断结果:\n')
f.write(check_result)
f.close()
def check_over_bound(self):
# 1. 越界判断
over_dict = {}
for i in range(len(self.df)):
for field in ['有效土层厚', '土壤容重', 'pH', '有机质', '有效磷', '速效钾']:
if self.df.loc[i, field] < OriginalCheck.BORDER_DICT.get(field)[0]:
# 越界字典的保存格式为{'固定编号': ['指标', '界限及界限值', '值']}
over_dict[self.df.loc[i, '固定编号']] = [field, f'下界{OriginalCheck.BORDER_DICT.get(field)[0]}',
self.df.loc[i, field]]
if self.df.loc[i, field] > OriginalCheck.BORDER_DICT.get(field)[1]:
over_dict[self.df.loc[i, '固定编号']] = [field, f'上界{OriginalCheck.BORDER_DICT.get(field)[1]}',
self.df.loc[i, field]]
# 2. 组织数据
check_result = ''
if over_dict:
for i, (key, [field, border, value]) in enumerate(over_dict.items(), 1): # enumerate(xxx, 1)表示从1开始编号
check_result += f'{i}. 固定编号为【{key}】 的 【{field}】指标越过了【{border}】,其值为【{value}】.\n'
else:
check_result = '无\n'
# 3. 将检测结果输出到txt
# 注意: open(path, 'a')以‘a’格式打开文件,表示文件不存在则创建文件,存在则追加到末尾。如果用‘w'模式打开则会覆盖前文空值检测的结果
f = open(OriginalCheck.OUTPUT_BASE_DIR + '\\' + self.county_name + '原始数据检测结果.txt', 'a')
f.write('\n以下为越界判断结果:\n')
f.write(check_result)
f.close()
if __name__ == '__main__':
for county_file in os.listdir(OriginalCheck.WORK_BASE_DIR):
check_obj = OriginalCheck(county_file)
check_obj.check_na()
check_obj.check_over_bound()
以下为检测报告: