# DataPreprocessing **Repository Path**: JasonXiao999/DataPreprocessing ## Basic Information - **Project Name**: DataPreprocessing - **Description**: No description available - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-07-26 - **Last Updated**: 2024-07-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README #
DataPreprocessing
## **
数据预处理工具集
** 此项目为 [大气环境数据挖掘实验室](https://wddzht.github.io/APDA.github.io/) 成员在大气污染物监测数据挖掘项目中常用的数据预处理方法整理,更多的是为数据处理分析的流程和方法做列举,仅供学习. 代码持续更新中,不足之处欢迎批评指正. [git here](https://github.com/Wddzht/DataPreprocessing) ## 目录结构: 1. **数据清洗** /DataCleaning 1. 空值处理 MissingDataHandle.py 1. 删除 delete_handle(data_class, handel_index) 2. 中位数插补 median_interpolation_handle(data_class, handel_index) 3. 众数插补 mode_interpolation_handle(data_class, handel_index) 4. 均值插补 mean_interpolation_handle(data_class, handel_index) 5. 固定值插补 fixed_value_padding_handle(data_class, handel_index, padding_value) 6. 间值法插补 mid_interpolation_handle(data_class, handel_index) 7. 线性回归法 8. 拉格朗日法 2. 异常值 OutlierHandle.py 1. Z-Score法 z_score_detection(data_class, handel_index, z_thr=3.0) 2. 滑动平均法 2. **数据集成** /Discretization 1. 合并 2. 去重 3. **数据变换** /DataTransformation 1. 函数变换 2. 归一化 NormalizeHandle.py 1. 离差标准化 min_max_normalize(data_class, handel_index) 2. 反离差标准化 anti_min_max_normalize(data_class, handel_index) 3. 标准化 StandardizationHandle.py 1. 标准化 standardization(data_class, handel_index) 2. 反标准化 anti_standardization(data_class, handel_index) 4. **数据规约** /DataReduction 1. 属性选择 RoughSetAttrSelecter 1. 基于粗糙集理论的属性选择 attribute_select(data_class) 5. **数据离散** /DataIntegration 1. 分箱 1. 等值分箱 2. 等频分箱 3. 基于Gini指数分箱 4. 基于熵增分箱 2. one-hot编码 6. **数据集结构** DataClass.py 1. 数据读取 read(self, path, has_head, split_tag='\t') 2. 数据格式转换 parse(self) 3. 打印 print(self) 7. **稀疏数据处理** 8. **日志记录** LogHelper.py --- ## 数据处理流程 ![avatar](https://raw.githubusercontent.com/Wddzht/DataPreprocessing/master/picture/%E6%B5%81%E7%A8%8B%E5%9B%BE.png) --- ## 一、数据表结构DataClass ### 1.1 属性: 1. 二维的数据表`data = [[]]` 2. 表头`head` 3. 每一列的数据类型`type_list` 4. 归一化时的最大值列表(用于反归一化)`normalize_max` 5. 归一化时的最小值列表(用于反归一化)`normalize_min` 6. 标准化时的均值(用于反标准化)`standard_mean` 7. 标准化时的标准差(用于反标准化)`standard_std` ### 1.2 方法: + 数据读取 `read(self, path, has_head, split_tag='\t'):` - path:文件路径 - has_head:是否有表头 - split_tag:切分字符 + 数据格式转换 `parse(self)` 在调用数据转换方法`parse(self)`时,格式错误的数据将被替换为空值. ```python {.line-numbers} data = DataClass([str] + [float] * 12) # 数据格式声明 data.read(r".\sample\fz_micro.txt", True) # 数据读取 data.parse() # 数据转换 ``` **数据样例 .\sample\fz_micro.txt (部分)** RECEIVETIME|CO|NO2|SO2|O3|PM25|PM10|TEMP|HUM|PM05N|PM1N|PM25N|PM10N :----|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----: 2017/1/9 18:00||634.38|619.43|733.52|57.33|57.76|15.19|65.14|4026.38|1944.57|401.29|24.81 2017/1/9 19:00|431.47|962.93|570.17|824.27|51.8|52.17|14|67.8|3646.73|1758.57|357.47|22.6 2017/1/9 20:00|423|756.33|556.43|854.57|48.57|48.73|14|68.3|3513|1687.4|339.77|20.7 2017/1/9 21:00|419.93|1008.57|499.47|908.13|46|46.47|13.8|68.33|3345.13|1600.43|326.17|20.87 2017/1/9 22:00||1019.47|476.07|927.67|46.27|46.77|13.03|68.83|3401.73|1633.37|328.7|18.83 2017/1/9 23:00||904.8|475.37|947.03|53.47|53.8|13|68.63|3838.1|1856.47|379.37|22.07 2017/1/10 0:00|412.9|1052.7|467.23|955.4|60.5|60.87|**A5**|68.3|4242.37|2075.77|428.53|25.93 2017/1/10 1:00|412.93|876.2|503.9|930.7|66.8|67.17|13|68.07|4635.37| --- ## 二、数据清洗 /DataCleaning ### 2.1 空值处理 MissingDataHandle.py #### 2.1.1 空值删除 delete_handle(data_class, handel_index) 1. `data_class`类型为DataClass的数据 2. `handel_index`要处理的列的下标 ```python {.line-numbers} import DataClass as dc data = dc.DataClass([str] + [float] * 12) data.read(r".\sample\fz_micro.txt", False) delete_handle(data,[i for i in range(1, 13)]) data.parse() ``` 处理后的 .data (空值删除并不会检查数据类型是否合法,如**A5**并不会被删除) RECEIVETIME|CO|NO2|SO2|O3|PM25|PM10|TEMP|HUM|PM05N|PM1N|PM25N|PM10N :----|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----: 2017/1/9 19:00|431.47|962.93|570.17|824.27|51.8|52.17|14|67.8|3646.73|1758.57|357.47|22.6 2017/1/9 20:00|423|756.33|556.43|854.57|48.57|48.73|14|68.3|3513|1687.4|339.77|20.7 2017/1/9 21:00|419.93|1008.57|499.47|908.13|46|46.47|13.8|68.33|3345.13|1600.43|326.17|20.87 2017/1/10 0:00|412.9|1052.7|467.23|955.4|60.5|60.87|**A5**|68.3|4242.37|2075.77|428.53|25.93 #### 2.1.2 均数填充 mean_interpolation_handle(data_class, handel_index) 要处理的属性必须是数值的,**不是数值元素按空值处理** 处理后的 .data RECEIVETIME|CO|NO2|SO2|O3|PM25|PM10|TEMP|HUM|PM05N|PM1N|PM25N|PM10N :----|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----: 2017/1/9 18:00|**411.02**|634.38|619.43|733.52|57.33|57.76|15.19|65.14|4026.38|1944.57|401.29|24.81 2017/1/9 19:00|431.47|962.93|570.17|824.27|51.8|52.17|14|67.8|3646.73|1758.57|357.47|22.6 2017/1/9 20:00|423|756.33|556.43|854.57|48.57|48.73|14|68.3|3513|1687.4|339.77|20.7 2017/1/9 21:00|419.93|1008.57|499.47|908.13|46|46.47|13.8|68.33|3345.13|1600.43|326.17|20.87 2017/1/9 22:00|**411.02**|1019.47|476.07|927.67|46.27|46.77|13.03|68.83|3401.73|1633.37|328.7|18.83 2017/1/9 23:00|**411.02**|904.8|475.37|947.03|53.47|53.8|13|68.63|3838.1|1856.47|379.37|22.07 2017/1/10 0:00|412.9|1052.7|467.23|955.4|60.5|60.87|**13.28**|68.3|4242.37|2075.77|428.53|25.93 2017/1/10 1:00|412.93|876.2|503.9|930.7|66.8|67.17|13|68.07|4635.37|**2279.67**|**469.8**|**28.93** #### 2.1.3 插值法填充 mid_interpolation_handle(data_class, handel_index) 要处理的属性必须是数值的,**不是数值元素按空值处理**. 1. 若空值处于首位,则插值取空值的下一个最近的非空的元素. 2. 若空值位于末尾,则插值取空值的上一个最近的非空的元素. 3. 若一个或多个连续的空值位于前后两个非空元素之间,则差值取前后非空元素的等差间值. 处理后的 .data RECEIVETIME|CO|NO2|SO2|O3|PM25|PM10|TEMP|HUM|PM05N|PM1N|PM25N|PM10N :----|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----: 2017/1/9 18:00|**431.47**|634.38|619.43|733.52|57.33|57.76|15.19|65.14|4026.38|1944.57|401.29|24.81 2017/1/9 19:00|431.47|962.93|570.17|824.27|51.8|52.17|14|67.8|3646.73|1758.57|357.47|22.6 2017/1/9 20:00|423|756.33|556.43|854.57|48.57|48.73|14|68.3|3513|1687.4|339.77|20.7 2017/1/9 21:00|419.93|1008.57|499.47|908.13|46|46.47|13.8|68.33|3345.13|1600.43|326.17|20.87 2017/1/9 22:00|**417.58**|1019.47|476.07|927.67|46.27|46.77|13.03|68.83|3401.73|1633.37|328.7|18.83 2017/1/9 23:00|**415.24**|904.8|475.37|947.03|53.47|53.8|13|68.63|3838.1|1856.47|379.37|22.07 2017/1/10 0:00|412.9|1052.7|467.23|955.4|60.5|60.87|**13**|68.3|4242.37|2075.77|428.53|25.93 2017/1/10 1:00|412.93|876.2|503.9|930.7|66.8|67.17|13|68.07|4635.37|**2360.77**|**489.71**|**29.58** #### 2.1.4+ 中数填充 众数填充 固定值填充 等 调用方法与插值法填充类似. ### 2.2 离异值(异常值)处理 OutlierHandle.py #### 2.2.1 Z-Score异常值检测 z_score_detection(data_class, handel_index, z_thr=3.0) 1. `data_class`类型为DataClass的数据. 2. `handel_index`要处理的列的下标. 3. `z_thr`识别阈值. 一般取 2.5, 3.0, 3.5 4. `:return`每一列离异值的下标. 条件:-1. 数据无空值. -2. 数据经过 parse() 方法格式转换.调用方法如下 ```python {.line-numbers} import DataClass as dc import DataCleaning.MissingDataHandle as mdh import DataCleaning.OutlierHandle as oh data = dc.DataClass([str] + [float] * 12) data.read(r".\sample\fz_micro.txt", False) data.parse() mdh.mid_interpolation_handle(data, [i for i in range(1, 13)]) # 插值法填充 oh.outlier_none_handle(data, [i for i in range(1, 13)], "z_score", 3.0) # 通过`z_score`方法识别异常,并置为空值 data.print() ``` --- ## 三、数据变换 /DataTransformation ### 3.1 归一化 NormalizeHandle.py #### 3.1.1 离差归一化 min_max_normalize(data_class, handel_index) ```python {.line-numbers} import DataClass as dc import DataCleaning.MissingDataHandle as mdh import DataTransformation.NormalizeHandle as nh data = dc.DataClass([str] + [float] * 12) data.read(r".\sample\fz_micro.txt", False) data.parse() mdh.mid_interpolation_handle(data, [i for i in range(1, 13)]) # 插值法填充 nh.min_max_normalize(data, [i for i in range(1, 13)]) # 离差归一化 data.print() ``` 条件:-1. 数据无空值. -2. 数据经过 parse() 方法格式转换处理. 处理后的 .data RECEIVETIME|CO|NO2|SO2|O3|PM25|PM10|TEMP|HUM|PM05N|PM1N|PM25N|PM10N :----|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----: 2017/1/9 18:00|0.87|0.27|0.83|0.31|0.48|0.48|0.55|0.52|0.54|0.51|0.45|0.36 2017/1/9 19:00|0.87|0.51|0.76|0.44|0.43|0.43|0.43|0.57|0.49|0.46|0.4|0.33 2017/1/9 20:00|0.71|0.36|0.74|0.48|0.4|0.4|0.43|0.58|0.47|0.44|0.37|0.3 2017/1/9 21:00|0.66|0.55|0.66|0.56|0.38|0.38|0.41|0.58|0.44|0.41|0.36|0.3 2017/1/9 22:00|0.61|0.56|0.63|0.59|0.38|0.38|0.34|0.59|0.45|0.42|0.36|0.27 2017/1/9 23:00|0.57|0.47|0.63|0.61|0.45|0.44|0.33|0.59|0.52|0.48|0.42|0.32 2017/1/10 0:00|0.52|0.58|0.61|0.63|0.51|0.5|0.33|0.58|0.58|0.54|0.48|0.38 2017/1/10 1:00|0.53|0.45|0.67|0.59|0.56|0.56|0.33|0.58|0.63|0.62|0.55|0.44 #### 3.1.2 反离差归一化 min_max_normalize(data_class, handel_index) 运行示例 ```python {.line-numbers} import DataClass as dc import DataCleaning.MissingDataHandle as mdh import DataTransformation.NormalizeHandle as nh data = dc.DataClass([str] + [float] * 12) data.read(r".\sample\fz_micro.txt", False) data.parse() mdh.mid_interpolation_handle(data, [i for i in range(1, 13)]) # 插值法填充 nh.min_max_normalize(data, [i for i in range(1, 13)]) # 离差归一化 nh.anti_min_max_normalize(data, [i for i in range(1, 13)]) # 反离差归一化 data.print() ``` 运行结果 RECEIVETIME|CO|NO2|SO2|O3|PM25|PM10|TEMP|HUM|PM05N|PM1N|PM25N|PM10N :----|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----: 2017/1/9 18:00|431.47|634.38|619.43|733.52|57.33|57.76|15.19|65.14|4026.38|1944.57|401.29|24.81 2017/1/9 19:00|431.47|962.93|570.17|824.27|51.80|52.17|14.00|67.80|3646.73|1758.57|357.47|22.60 2017/1/9 20:00|423.00|756.33|556.43|854.57|48.57|48.73|14.00|68.30|3513.00|1687.40|339.77|20.70 2017/1/9 21:00|419.93|1008.57|499.47|908.13|46.00|46.47|13.80|68.33|3345.13|1600.43|326.17|20.87 2017/1/9 22:00|417.59|1019.47|476.07|927.67|46.27|46.77|13.03|68.83|3401.73|1633.37|328.70|18.83 2017/1/9 23:00|415.24|904.80|475.37|947.03|53.47|53.80|13.00|68.63|3838.10|1856.47|379.37|22.07 2017/1/10 0:00|412.90|1052.70|467.23|955.40|60.50|60.87|13.00|68.30|4242.37|2075.77|428.53|25.93 2017/1/10 1:00|412.93|876.20|503.90|930.70|66.80|67.17|13.00|68.07|4635.37|2360.77|489.71|29.58 ### 3.2 标准化 StandardizationHandle.py #### 3.2.1 标准化 standardization(data_class, handel_index) ```python {.line-numbers} import DataClass as dc import DataTransformation.StandardizationHandle as sdh data = dc.DataClass([str] + [float] * 12) data.read(r"E:\_Python\DataPreprocessing\sample\fz_micro.txt", False) data.parse() mdh.mid_interpolation_handle(data, [i for i in range(1, 13)]) # 插值法填充 sdh.standardization(data, [i for i in range(1, 13)]) # 标准化 data.print() ``` 条件:-1.数据无空值 -2.数据经过 parse() 方法格式转换. 执行结果 RECEIVETIME|CO|NO2|SO2|O3|PM25|PM10|TEMP|HUM|PM05N|PM1N|PM25N|PM10N :----|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----: 2017/1/9 18:00|1.47|-0.29|0.80|-0.81|0.05|0.04|1.04|-0.44|0.08|0.06|0.02|-0.14 2017/1/9 19:00|1.47|0.89|0.50|-0.21|-0.16|-0.17|0.39|-0.20|-0.16|-0.16|-0.22|-0.30 2017/1/9 20:00|0.86|0.15|0.42|-0.01|-0.29|-0.30|0.39|-0.16|-0.25|-0.25|-0.31|-0.44 2017/1/9 21:00|0.63|1.06|0.07|0.35|-0.39|-0.39|0.28|-0.15|-0.35|-0.35|-0.38|-0.42 2017/1/9 22:00|0.46|1.10|-0.08|0.48|-0.38|-0.38|-0.14|-0.11|-0.32|-0.31|-0.37|-0.57 2017/1/9 23:00|0.29|0.68|-0.08|0.60|-0.10|-0.11|-0.15|-0.13|-0.04|-0.05|-0.10|-0.34 2017/1/10 0:00|0.12|1.22|-0.13|0.66|0.17|0.16|-0.15|-0.16|0.22|0.21|0.16|-0.06 2017/1/10 1:00|0.12|0.58|0.09|0.50|0.41|0.40|-0.15|-0.18|0.46|0.55|0.49|0.21 #### 3.2.2 反标准化 anti_standardization(data_class, handel_index) 运行示例 ```python {.line-numbers} import DataClass as dc import DataTransformation.StandardizationHandle as sdh data = dc.DataClass([str] + [float] * 12) data.read(r"E:\_Python\DataPreprocessing\sample\fz_micro.txt", False) data.parse() mdh.mid_interpolation_handle(data, [i for i in range(1, 13)]) # 插值法填充 sdh.standardization(data, [i for i in range(1, 13)]) # 标准化 sdh.anti_standardization(data, [i for i in range(1, 13)]) # 反标准化 data.print() ``` --- ## 四、数据规约 /DataReduction ### 4.1 属性选择 RoughSetAttrSelecter.py #### 4.1.1 基于粗糙集理论的属性选择 attribute_select(data_class) Workflow: 1. 计算数据的CORE属性集:`core = get_core(dc)`, 2. 以CORE中的属性作为初始的属性选择,检查在选定的属性集下,是否存在不可区分集(即计算选定属性集在所有决策属性的下近似) ``check_distinct(dc, core, considered_instence)`` $$Initial\:SelectedAttrs=\{CORE\}$$ $$POS_{\{SelectedAttrs\}}(D)=U_{CX}$$ 3. 若存在不可区分集,进行下一步迭代.若不存在不可区分集,则CORE就是Reduct. 4. 从剩下的属性中依次选取一个属性$a_i$加入:$$SelectedAttrs=\{CORE\}+\{a_i\}$$ 检查在选定的属性集下,是否存在不可区分集. 5. 若存在一个或多个个数相同的属性集,都不会产生不可区分集,则在这些属性中选取值种类数较少的属性加入并返回SelectedAttrs,并返回SelectedAttrs,程序运行结束. 6. 若对于所有的$\{CORE\}+\{a_i\}$属性集,都会产生不可区分集(没有 Reduct )),则选择区分集个数最少的属性进入下一轮迭代(第4步). **Case 1:** data: (其中a,b,c,d为条件属性, E为决策属性) U|a|b|c|d|**E** :----|-----:|-----:|-----:|-----:|-----: u1|1|0|2|1|1 u2|1|0|2|0|1 u3|1|2|0|0|2 u4|1|2|2|1|0 u5|2|1|0|0|2 u6|2|1|1|0|2 u7|2|1|2|1|1 ```python {.line-numbers} # 方法测试 dc = DataClass.DataClass([str] * 5, data) core = get_core(dc) assert core == [1] # CORE(cd)=1 (the second attr) considered_instence = np.array([True] * dc.len, np.bool) is_reduct, classify_num, considered_instence = check_distinct(dc, core, considered_instence) assert (is_reduct, classify_num, considered_instence) == (False, 1, [False] * 2 + [True] * 5) # 属性选择 selected_attr, max_classify_num = attribute_select(dc) assert selected_attr == [1, 3] # 选择{b,d}作为约简后的属性集 ``` 方法说明: 其中`get_core(data)`方法通过构造 Discernibility Matrix 的方法选出CORE属性. `check_distinct`方法用来检查在选定的属性集下,是否存在**不可区分集**. 并返回**分类个数**和**数据集约简** 不可区分集: 存在两条或多条记录,它们的(已选择的)条件属性相同,但对应的决策属性不同,则这些记录构成了不可区分集,如:当选择{a,b}作为Reduct时, U|a|b|**E** :----|-----:|-----:|-----: u3|1|2|2 u4|1|2|0 u5|2|1|2 u6|2|1|2 u7|2|1|1 a1b2→E2, a1b2→E0 ({u3,u4}构成不可区分集) a2b1→E2, a2b1→E1 (\{u5,u6,u7}构成不可区分集) **Case 2:** ```python {.line-numbers} # [case2] dc = DataClass.DataClass([str] * 5) dc.read(r'..\sample\weather.txt', True) selected_attr, max_classify_num = attribute_select(dc) assert selected_attr == {0, 1, 3} # 选择属性 {Outlook, Temperature, Windy} ``` Weather数据集: U|Outlook|Temperature|Humidity|Windy|**Play** :----|-----:|-----:|-----:|-----:|-----: x1|sunny|hot|high|false|no x2|sunny|hot|high|true|no x3|overcast|hot|high|false|yes x4|rainy|mild|high|false|yes x5|rainy|cool|normal|false|no x6|overcast|cool|normal|true|yes x7|sunny|mild|high|false|no x8|sunny|cool|normal|false|yes x9|rainy|mild|normal|false|yes x10|sunny|mild|normal|true|yes x11|overcast|mild|high|true|yes x12|overcast|hot|normal|false|yes x13|rainy|mild|high|true|no 属性化简后的数据: U|Outlook|Temperature|Windy|**Play** :----|-----:|-----:|-----:|-----: x1|sunny|hot|false|no x2|sunny|hot|true|no x3|overcast|hot|false|yes x4|rainy|mild|false|yes x5|rainy|cool|false|no x6|overcast|cool|true|yes x7|sunny|mild|false|no x8|sunny|cool|false|yes x9|rainy|mild|false|yes x10|sunny|mild|true|yes x11|overcast|mild|true|yes x12|overcast|hot|false|yes x13|rainy|mild|true|no ---