Python:数据抽样平衡方法重写
时间:2022-06-07
本文章向大家介绍Python:数据抽样平衡方法重写,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
之前在R里面可以通过调用Rose这个package调用数据平衡函数,这边用python改写了一下,也算是自我学习了。
R:
#设定工作目录
setwd(path)
# 安装包
install.packages("ROSE")
library(ROSE)
#检查数据
data(hacide)
table(hacide.train$cls)
0 1
980 20
过抽样实现:
data_balanced_over <- ovun.sample(cls ~ ., data = hacide.train, method = "over",N = 1960)$data
table(data_balanced_over$cls)
0 1
980 980
这边需要注意是ovun
不是over
欠采样实现:
data_balanced_under <- ovun.sample(cls ~ ., data = hacide.train, method = "under", N = 40, seed = 1)$data
table(data_balanced_under$cls)
0 1
20 20
这边需要注意的是欠采样是不放回采样,同时对数据信息的损失也是极大的
组合采样实现:
data_balanced_both <- ovun.sample(cls ~ ., data = hacide.train, method = "both", p=0.5, N=1000, seed = 1)$data
table(data_balanced_both$cls)
0 1
520 480
method
的不同值代表着不同的采样方法,p这边是控制正类的占比,seed保证抽取样本的固定,也就是种子值。
在python上,我也没有发现有现成的package可以import,所以就参考了R的实现逻辑重写了一遍,新增了一个分层抽样group_sample
,删除了过采样,重写了组合抽样combine_sample
,欠抽样under_sample
:
# -*- coding:utf-8 -*-
import pandas as pd
import random as rd
import numpy as np
import math as ma
class sample_s(object):
def __init__(self):
''''this is my pleasure'''
def group_sample(self, data_set, label, percent=0.1):
# 分层抽样
# data_set:数据集
# label:分层变量
# percent:抽样占比
# q:每次抽取是否随机,null为随机
# 抽样根据目标列分层,自动将样本数较多的样本分层按percent抽样,得到目标列样本较多的特征欠抽样数据
x = data_set
y = label
z = percent
diff_case = pd.DataFrame(x[y]).drop_duplicates([y])
result = []
result = pd.DataFrame(result)
for i in range(len(diff_case)):
k = np.array(diff_case)[i]
data_set = x[x[y] == k[0]]
nrow_nb = data_set.iloc[:, 0].count()
data_set.index = range(nrow_nb)
index_id = rd.sample(range(nrow_nb), int(nrow_nb * z))
result = pd.concat([result, data_set.iloc[index_id, :]], axis=0)
new_data = pd.Series(result['label']).value_counts()
new_data = pd.DataFrame(new_data)
new_data.columns = ['cnt']
k1 = pd.DataFrame(new_data.index)
k2 = new_data['cnt']
new_data = pd.concat([k1, k2], axis=1)
new_data.columns = ['id', 'cnt']
max_cnt = max(new_data['cnt'])
k3 = new_data[new_data['cnt'] == max_cnt]['id']
result = result[result[y] == k3[0]]
return result
def under_sample(self, data_set, label, percent=0.1, q=1):
# 欠抽样
# data_set:数据集
# label:抽样标签
# percent:抽样占比
# q:每次抽取是否随机
# 抽样根据目标列分层,自动将样本数较多的样本按percent抽样,得到目标列样本较多特征的欠抽样数据
x = data_set
y = label
z = percent
diff_case = pd.DataFrame(pd.Series(x[y]).value_counts())
diff_case.columns = ['cnt']
k1 = pd.DataFrame(diff_case.index)
k2 = diff_case['cnt']
diff_case = pd.concat([k1, k2], axis=1)
diff_case.columns = ['id', 'cnt']
max_cnt = max(diff_case['cnt'])
k3 = diff_case[diff_case['cnt'] == max_cnt]['id']
new_data = x[x[y] == k3[0]].sample(frac=z, random_state=q, axis=0)
return new_data
def combine_sample(self, data_set, label, number, percent=0.35, q=1):
# 组合抽样
# data_set:数据集
# label:目标列
# number:计划抽取多类及少类样本和
# percent:少类样本占比
# q:每次抽取是否随机
# 设定总的期待样本数量,及少类样本占比,采取多类样本欠抽样,少类样本过抽样的组合形式
x = data_set
y = label
n = number
p = percent
diff_case = pd.DataFrame(pd.Series(x[y]).value_counts())
diff_case.columns = ['cnt']
k1 = pd.DataFrame(diff_case.index)
k2 = diff_case['cnt']
diff_case = pd.concat([k1, k2], axis=1)
diff_case.columns = ['id', 'cnt']
max_cnt = max(diff_case['cnt'])
k3 = diff_case[diff_case['cnt'] == max_cnt]['id']
k4 = diff_case[diff_case['cnt'] != max_cnt]['id']
n1 = p * n
n2 = n - n1
fre1 = n2 / float(x[x[y] == k3[0]]['label'].count())
fre2 = n1 / float(x[x[y] == k4[1]]['label'].count())
fre3 = ma.modf(fre2)
new_data1 = x[x[y] == k3[0]].sample(frac=fre1, random_state=q, axis=0)
new_data2 = x[x[y] == k4[1]].sample(frac=fre3[0], random_state=q, axis=0)
test_data = pd.DataFrame([])
if int(fre3[1]) > 0:
i = 0
while i < (int(fre3[1])):
data = x[x[y] == k4[1]]
test_data = pd.concat([test_data, data], axis=0)
i += 1
result = pd.concat([new_data1, new_data2, test_data], axis=0)
return result
后续使用,只需要复制上述code,存成.py
的文件,后续使用的时候:
#加载函数
import sample_s as sa
#这边可以选择你需要的分层抽样、欠抽样、组合抽样的函数
sample = sa.group_sample()
#直接调用函数即可
new_data3 = sample.combine_sample(data_train, 'label', 60000, 0.4)
#将data_train里面的label保持正样本(少类样本)达到0.4的占比下,总数抽取到60000个样本
其实不是很难的一个过程,只是强化自己对python及R语言的书写方式的记忆,谢谢。
- Java中static关键字的作用
- Java基础-20(02)总结,递归,IO流
- Hive四种数据导入方式
- 34c3 部分Web Writeup
- 原来Oracle也不喜欢“蜀黍"(r6笔记第54天)
- Java基础19(01)总结IO流,异常try…catch,throws,File类
- 使用shell生成orabbix自动化配置脚本(r6笔记第53天)
- 现在 tensorflow 和 mxnet 很火,是否还有必要学习 scikit-learn 等框架?
- 数据的标准化与中心化以及R语言中的scale详解
- Java基础19(02)总结IO流,异常try…catch,throws,File类
- HTML5 — header
- 两条报警信息的分析(第二篇)(r6笔记第71天)
- 两条报警信息的分析(第一篇) (r6笔记第70天)
- R-求y=sin(X) 0-PI 面积代码
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- golang判断map中key是否存在的方法
- 迁移实战:一次AntDB(基于pgxl分布式架构的数据库)数据库迁移经验分享
- 看完这篇文章,99%的人都会使用Mysql Explain工具
- 浅析MySQL存储引擎序列属性
- 详述MySQL Using intersect交集算法
- 案例:强制开库遭遇ORA-16433的处理过程
- 叮~AutoML自动化机器学习入门指南,来了
- 注意:ORACLE 11G ADG RAC 这个情况下并不能高可用
- Nginx转发指向数据库端口并对外开放访问权限
- Python手写了 35 种可解释的特征工程方法
- Geant4--G4ParticleGun定义射线源的发射能谱
- Sony-PMCA-RE, 反向工程索尼PlayMemories相机应用
- 中标麒麟系统Your trial is EXPIRED and no VALID licens
- R初探
- 独家 | 在Python编程面试前需要学会的10个算法(附代码)