广告点击案例分析

#读入数据

import pandas as pd

import numpy as np

from sklearn.preprocessing import OrdinalEncoder

from sklearn.ensemble import IsolationForest

raw_data = pd.read_csv('./outlier.txt',sep=',')

print('shape:',raw_data.shape)

raw_data.head()

#out:  shape: (10492, 47)

看一下数据的info()和describe()

raw_data.info()

raw_data.describe()

发现有缺失值,和方差为0的项

#全为NaN的列

nanlist1 = raw_data.columns[np.all(raw_data.isna(),axis=0)]

#包括Nan的列

nanlist2 = raw_data.columns[np.any(raw_data.isna(),axis=0)]

#删除全为NaN的列

df1 = raw_data.drop(columns=nanlist1)

#填充包括Nan的列

df2 = df1.fillna({'newVisits': 0, 'pageviews': 0, 'isVideoAd': False, 'isTrueDirect': False})

#删除方差为0的列

#std=0的列

zero_std = df2.describe().columns[df2.describe().loc['std',:]==0]

#Out: Index(['visits'], dtype='object')

df3 = df2.drop(columns=zero_std)

df3.shape

#out:  (10492, 44)

删除了全为空和方差为零的特征,同时做了Nan的填充,再填充的时候我们需要查看缺失列的数据分布,再尝试填充。

#查看应该填充什么样的缺失值

raw_data['isVideoAd'].value_counts()

#False    122

# Name: isVideoAd, dtype: int64

为了使用ISOlation Forest检测异常点,首先需要将离散的特征值用OrdinalEncoder替换成数值型。

#取出dtype=='object'的列

str_cols = df3[df3.columns[df3.dtypes=='object']]

##取出dtype!='object'的列

num_cols = df3[df3.columns[df3.dtypes!='object']]

# 分类特征转换为数值型索引

model_oe = OrdinalEncoder()

string_data_con = model_oe.fit_transform(str_cols)

string_data_pd = pd.DataFrame(string_data_con,columns=str_cols.columns)

#删除方差为0的列

#std=0的列

str_zero_std = string_data_pd.describe().columns[string_data_pd.describe().loc['std',:]==0]

# OUt: Index(['socialEngagementType'], dtype='object')

string_data_pd=string_data_pd.drop('socialEngagementType',axis=1)

#合并str和nums 列

df_merge = pd.concat((num_cols,string_data_pd),axis=1).drop('clientId',axis=1)

#使用ISOlation Forest检测异常点

IF_model = IsolationForest(n_estimators=1000,n_jobs=-1)

outlier_lable = IF_model.fit_predict(df_merge)

# IsolationForest(behaviour='deprecated', bootstrap=False, contamination='auto',

#                max_features=1.0, max_samples='auto', n_estimators=1000,

#                n_jobs=-1, random_state=None, verbose=0, warm_start=False)

再初始DF中添加是否异常特征

#添加是否异常列

df3['isout']=outlier_lable

df3['isout'].value_counts()

#OUT:

# 1    8813

# -1    1679

# Name: isout, dtype: int64

可以看到IF分出的异常点占比还挺大的。

接下来按照渠道对数据分类并聚合得到各个渠道的异常比例

isnormal = df3[df3['isout']==1].groupby('source',as_index=False)[['isout']].count()

notnormal= df3[df3['isout']==-1].groupby('source',as_index=False)[['isout']].count()

nor_df=  pd.merge(notnormal,isnormal,how='outer',on='source')

nor_df = nor_df.fillna(0)

#统计每个渠道的异常情况

df_source = df3.groupby('source',as_index=False)[['isout']].count().sort_values('isout',ascending=False)

df_source=  pd.merge(nor_df,df_source,how='outer',on='source')

df_source['outlier_rate'] = df_source['isout_x']/df_source['isout']

df_source = df_source.sort_values('isout',ascending=False)

df_source


#计算总体平均异常点击概率

mean_outrate = df_source.sum()['isout_x']/df_source.sum()['isout']

# 0.1598360655737705

#点击大于10,异常小于平均(good)

df_source.query('isout>=10 & outlier_rate<0.1598360655737705')

#点击大于10,异常大于平均(bad)

df_source.query('isout>=10 & outlier_rate>=0.1598360655737705')


由于样本没有明确的标签值,所以我们通过算法判断出来的结果不一定可靠,但可以作为一个参考。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容