pandas特征工程的处理小结

特征工程的处理小结

基本的数据特征:
在这里插入图片描述

预处理

1、查看数据的基本信息

data.info :查看数据的基本结构组成和对应的属性

data.shape:查看数据的行数和列数

data.head(n):显示数据的前n行

data.columns:显示所有的列名

data.columns = [“A”“C”“W"d"d"e”] :按顺序设置新的列名

更改列名
data.rename(columns={'id':'ID', '原来的列名':'新的列名'}) 

2、统计列的情况

data[column].value_counts():显示每一列对应的分类,每一类的个数/比例

'''
获取columnName对应列的各个分类的数量和比例
'''
def getColumnNumsAndRatio(columnName, data, dropNan=True, sort=True, normalize=True):
    # 获取某一列的各类别的个数
    cat_nums = data[columnName].value_counts()
    # 获取某一列各类别的占比
    cat_ratio = data[columnName].value_counts(normalize = normalize)
    # 组合个数、占比
    numAndRatio = pd.concat([cat_nums, cat_ratio],axis=1)
    # 更改列名
    numAndRatio.columns = [columnName+'各分类数量', columnName+'各分类占比']
    return numAndRatio

3、统计缺失信息

'''
获取数据中每个特征缺失的情况
'''
def getNullInfoAboutColumns(data):
    missNumber = data.isnull().sum().sort_values(ascending = False)
    missPercent = (missNumber / data.shape[0]).sort_values(ascending = False)
    nullNumberAndPrecent = pd.concat([missNumber, missPercent], axis =1, keys = ['缺失数量','缺失占比'])
    return nullNumberAndPrecent

缺失样本处理

4、重复样本

# 统计重复的样本个数
data.duplicated().sum() 

# 删除重复的样本
data.drop_duplicates(inplace = True)

5、各列的数据箱式分布

# 所有数据的分布情况
data.describe()

# 对应column列的分布情况
data[column].describe()

绘制概率密度图

import seaborn as sns

plt.figure(figsize=(10, 8), dpi=80)
#绘图
sns.kdeplot(data["订单金额"],  # 对应的列
            shade=True,
            color="#01a2d9",  # 颜色
            label="订单金额",
            alpha=.7)
#风格与装饰
sns.set(style="whitegrid", font_scale=1.1)
plt.title("订单金额概率密度分布图",fontsize=18)
plt.yticks([])
plt.xlim((-1,40000))
plt.show()

获取对应列异常值的索引

'''
columns: list列表
'''
def getFeatureAbnormalIndex(data, columns):
    numOfSample = data.shape[0]
    listAbnormalIdx = []
    
    for idx, column in enumerate(columns):
        feature = data[column]
        # 获取25%的数据值
        QL = feature.quantile(0.25)
        # 获取75%的数据值
        QU = feature.quantile(0.75)
        IQR = QU - QL
        # 异常值的定义方式
        abnormal = feature[((feature < (QL - 1.5 * IQR)).astype(int) +  (feature > (QU + 1.5*IQR)).astype(int)) !=0]
        listAbnormalIdx.extend(abnormal.index)
    # 去重
    listAbnormalIdx = list(set(listAbnormalIdx))
    return listAbnormalIdx

创建新的数据并计算和之前列的相关系数

'''
column:列名
newColumn:增加列的名称
newColumnIndex:list 对应这些的索引值需要改变
'''
def makeNewFeatureAndcomputeCorration(data, column, newColumn, newColumnIndex):
    # 创建索引和需要建立相关系数的列相同的缩影
    df = pd.DataFrame(index = data.index)
    # 设置初始值
    df[newColumn] = 0
    # 设置需要改变的值
    df.loc[newColumnIndex, newColumn] = 1
    # 计算相关系数
    corration = pd.concat([df[newColumn], data[column]], axis=1).corr()
    return corration

6、数据提取

loc提取:按标签提取

iloc提取:按照位置进行提取

data[]提取

data[]可以输入的值

只能是单独对应列的名称,取一列

df = pd.DataFrame([(.2, .3, 2.5), (.0, .6, 3.6), (.6, .0, .3), (.2, .1, .2)],columns=['dogs', 'cats', 'pig'], index=list("ABCD"))
# 只能单独索引列
df['dogs']
df['pig']

pandas.DataFrame.loc() 允许输入的值:

  • 单个标签,例如5或’a’,(请注意,5被解释为索引的标签,而不是沿索引的整数位置)。
  • 标签列表或数组,可以是对应行或者列,或者行和列,例如。[‘a’, ‘b’, ‘c’]
  • 具有标签的切片对象,例如’a’:‘f’,切片的开始和结束都包括在内。
df = pd.DataFrame([(.2, .3, 2.5), (.0, .6, 3.6), (.6, .0, .3), (.2, .1, .2)],columns=['dogs', 'cats', 'pig'], index=list("ABCD"))

# 索引行
    # 单一索引行
    df.loc['A']
    # 搜索若干行,对应行的列表即可
    df.loc[["A", "B"]]
# 索引列
	# 单一索引一列列
    df.loc[:,'dogs']
    # 搜索若干行,对应行的列表即可
    df.loc[:,["dogs", "pigs"]]
    
# 索引某行某列
	# 确定的值
    df.loc['A', "dogs"]
    # 搜索若干行,若干列
    df.loc[["A", "B"],['dogs', 'pig']]
    df.loc[["A", "B"],:]

pandas.DataFrame.iloc()允许输入的值:

整数5、整数列表或数组[4,3,0]、整数的切片对象1:7

df = pd.DataFrame([(.2, .3, 2.5), (.0, .6, 3.6), (.6, .0, .3), (.2, .1, .2)],columns=['dogs', 'cats', 'pig'], index=list("ABCD"))
#对应的索引坐标或者切片,列表
df.iloc[x,y]
df.iloc[2]
df.iloc[2:,1:]
df.iloc[1,2]
df.iloc[[1,3],[1,2]]

选取满足的值进行选取

1、将满足origin是China且money小于35这两个条件的数据,返回其id、date、money、product、department、origin值。

data.loc[(data['origin']=="China") & (data['money']<35),['id','date','money','product','department','origin']]

2、将满足origin是China或者money小于35这两个条件之中任意一个条件的数据,返回其id、date、money、product、department、origin值。

data.loc[(data['origin']=="China") | (data['money']<35),['id','date','money','product','department','origin']]

值的判断

方式一:判断origin列的值是否为China

data['origin']=="China"

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w48usB9L-1642064510741)(C:\Users\zjy\Desktop\xiangmu\数据分析项目\国美异常检测\图片\image-20220113002738368.png)]

方式二:判断department列的值是否为水果

data['department'].isin(['水果'])

提取符合判断的值

data.loc[data['origin'].isin(['Thailand'])]    # 将产地是泰国的数据进行提取

7、手动划分数据集

选取一个特征进行去重

'''
选取一列进行去重
column: str
'''
def getUniqueByColumn(data, column):
    uniqueColumn = data[column].unique()
    return uniqueColumn

按比例划分数据集train、test

'''
划分数据集
column: str 按照数据的某一列划分
uniqueColumn: 某一列的数据
sampleRatio: 抽样比例
'''
def makeTrainAndTestData(data, column, uniqueColumn, sampleRatio=0.3):
    # 按抽样比例随机选取某一指定列作为测试集一列
    testDataOneColumn = random.sample(uniqueColumn.tolist(), int(len(uniqueColumn)*sampleRatio))
    
    # 选取不包含测试样本的数据
    train = data.loc[~data[column].isin(testDataOneColumn)]
    # 选取包含测试样本的数据的所有测试样本
    test = data.loc[data[column].isin(testDataOneColumn)]
    
    # 更显train和test的index
    train.index = range(len(train))
    test.index = range(len(test))
    return train, test

8、数据的异常率新特征

(1)查看某列的异常率,通常这一列中的分类适中,可以计算出每一个类中的异常率,最终使用map映射创建出新的特征列

'''
分析每一列中的特征对应的异常率
groupByColumn: 用来聚类的列
column: 一般为标签的列
'''
def getColumnAbnormalRatio(data, groupByColumn, column):
    # 计算出每个类别的异常概率,如果分类标签不同方法要进行改变
    abnormal = data.groupby(groupByColumn)[column].mean()
    df = pd.concat([abnormal, 1-abnormal], axis = 1, keys=["异常率", "正常率"])
    return df

绘制条形对比图

from pyecharts.charts import *
from pyecharts.components import Table
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode
bar_hour = (
    Bar(init_opts=opts.InitOpts())  
    .add_xaxis(ab_hour.index.to_list())
    .add_yaxis("异常交易", round(ab_hour['异常率'],3).to_list(),stack = True)
    .add_yaxis("正常交易", round(ab_hour['正常率'],3).to_list(),stack = True)
    .set_global_opts(title_opts=opts.TitleOpts(title="【"+'下单小时'+'】'+"异常交易/全部交易的比例")
                    , xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)))
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False),xaxis_opts=opts.AxisOpts(name_rotate = 90))
)

bar_hour.render_notebook()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TVhE7cKF-1642064510743)(C:\Users\zjy\Desktop\xiangmu\数据分析项目\国美异常检测\图片\条形图)]

(2)创建新的特征

创建字典:只是用列就可以创建列和索引的字典

dict(data[column])

复杂字典:某列中类别对应的异常率

def getDict(data, groupByColumn, labelColumn):
    dic = dict(data.groupby(groupByColumn)[labelColumn].mean())
    return dic
'''
创建新特征
groupByColumn:分组列
labelColumn:标签列
column:老列的名称
newColumn: 新列的名称
'''
def groupByCreateFeature(train, test, groupByColumn, labelColumn, column, newColumn):
    # 利用训练集数据构建字典
    dic = getDict(train, groupByColumn, labelColumn)
    
    #建立新的特征
    train[newColumn] = train[column].map(dic)
    test[newColumn] = test[column].map(dic)
    return train, test

(3)将文字特征进行顺序编码

def easyCodeByTrainAndTest(column, train, test):
    # 利用train创建字典
    dic = {}
    feature = np.sort(train[column].unique())
    for code, cat in enumerate(feature):
        dic[cat] = code
        
    #更新train内的字段
    train[column] = train[column].map(dic)
    
    #根据test增加字典  test[column].map(dic).isnull()按照原来字典更新后为null的列的值
    newCat = test.loc[test[column].map(dic).isnull(),column].unique()
    for i in newCat:
        dic[i] = len(dic)
        
    #更新test字段
    test[column] = test[column].map(dic)
    return train, test

创建字典

# 完成了索引对应列的字典
dict(df[column])

9、异常率的阈值处理法

用户ID、商品ID、品牌的特点:

①相较于之前处理的特征(商品一级类别、商品所属渠道、支付方式等)其各特征下的类别拥有交易量足够、可以衡量风险的类型;但用户ID、商品ID、品牌,这三者因为其特征下的类别较多,拥有交易过少无法判断的特点。为此,我们像先前一样新增特征“XX异常率”,但不同的是,需对未达到阈值(人为设定)的异常率特征记为-1

②用户ID、商品ID、品牌因为类别多,其特征拥有部分类别只存在于训练集,不存在与测试集的特点,为此在新增特征“XX异常率”时,这些在测试集未出现的类别对应的异常率记为-1;在特征编码时,将对这些类目手动新增

'''
获取某一分组满足特征条件的概率
比如对应品牌中,销售的数量大于10
groupByColumn 分组列
labelColumn    标签列
conditionColumn 条件列
threshold: 满足阈值的条件
'''
def columnRatioSatifyCondition(data, groupByColumn, labelColumn, conditionColumn, threshold):
    columnRatio = data.groupby(groupByColumn)[labelColumn].mean()[data.groupby(groupByColumn)[conditionColumn].sum() > threshold ]
    return columnRatio
'''
生成新的Data,
curColumnName: 当前处理的特征列
newColumnName: 新增特征的名称
multiplyRatio: columnRatioSatifyCondition()产生的值,满足当前列某一条件的概率进行赋值
initVal=-1:     Data的初始值
'''
def getMulColumnConditionRatio(data, curColumnName, newColumnName, multiplyRatio, initVal=-1):
    df = pd.DataFrame(index = data[curColumnName].unique())
    df[newColumnName] = initVal
    df.loc[multiplyRatio.index, newColumnName] = multiplyRatio
    return df
# ratio是指满足某条件下的某一特征的异常率columnRatioSatifyCondition产生的值

def groupByFeatureMore(column, train, test, newColumn, ratio):
    #创建训练集字典
    # 新建数据,并指定索引
    df = pd.DataFrame(index = train[column].unique())
    # df新增一列设置处置为-1
    df[newColumn] = -1
    # 设置ratio中的值
    df.loc[ratio.index, newColumn] = ratio
    # 创建字典
    trainDic = dict(df[newColumn])
    
    #训练集映射
    train[newColumn] = train[column].map(trainDic)
    
    #测试集构建字典,出现在训练集的直接赋值,没有出现的设置-1
    testDic = {}
    for i in test[column]:
        if i in ratio.index:
            testDic[i] = ratio[i]
        else:
            testDic[i] = -1
    
    #测试集映射
    test[newColumn] = test[column].map(testDic)
    return train, test

10、连续值分箱特征处理

有些特征的值是连续的比如订单金额与销售数量。可以先将金额进行分箱,再利用分箱数进行统计异常率。

绘制异常和正常情况的概率密度:

abnormal = train.loc[train['异常']==1, '订单金额']
normal = train.loc[train['异常'==0], '订单金额']

绘制密度分布图

plt.figure(figsize=(10, 8), dpi=80)
sns.kdeplot(normal,
            shade=True,
            color="#01a2d9",
            label="normal",
            alpha=.5)  #透明度
sns.kdeplot(abnormal,
            shade=True,
            color="#dc2624",
            label="abnormal",
            alpha=.9)

#风格与装饰
sns.set(style="whitegrid",font="SimHei", font_scale=1.1)
plt.title("abnormal vs normal the pic of money",fontsize=18)
#plt.yticks([])
# 可以通过这个具体看每个分段的具体分布
plt.xlim((0, 100))
plt.ylim((0,0.000002))
plt.show()

特征分箱

from sklearn.preprocessing import KBinsDiscretizer as KBD
def getColumnBinsDiscretizer(train, test, curColumnName, newColumnName, bins):
    # 编码方式为顺序编码,策略为kmeans,分了10个箱
    enc = KBD(n_bins=bins, encode='ordinal', strategy='kmeans')
    enc = enc.fit(pd.DataFrame(train[curColumnName]))
    
    # 进行新特征的赋值
    train[newColumnName] = enc.transform(pd.DataFrame(train[curColumnName]))
    test[newColumnName] = enc.transform(pd.DataFrame(test[curColumnName]))
    return train, test
# 创建字典
def createNewFeature(train, test, groupbyColumnName, labelColumnName, newColumnName):
    # 构造字典
    dic = dict(train.groupby(groupbyColumnName)[labelColumnName].mean())

    # train和test更新特征列
    train[newColumnName] = train[groupbyColumnName].map(dic)
    test[newColumnName]  = test[groupbyColumnName].map(dic)
    return train, test

创建二值分箱:

这个针对的特征是,在一定范围内无法区分是异常还是非异常,在阈值外大部分是异常可使用简单二值分箱

'''
对某一特征进行二值分析
'''
def createBinaryFeature(train, test, curColumnName, newColumnName, threshold):
    # 增加新列并且设置初始值
    train[newColumnName] = 0
    test[newColumnName] = 0
    
    #将满足指定阈值的
    train.loc[train[curColumnName] > threshold, newColumnName] = 1
    test.loc[test[curColumnName] > threshold, newColumnName] = 1
    return train, test

参考文章

pandas数据分析常用函数总结(下篇) - 知乎 (zhihu.com))

[国美在线商城异常订单检测](国美线上商城的异常订单检测 - Heywhale.com)

你可能感兴趣的:(torch,python,python,数据分析,pytorch)