电商-广告投放效果分析(KMeans聚类、数据分析-pyhton数据分析

电商-广告投放效果分析(KMeans聚类、数据分析)

文章目录

  • 电商-广告投放效果分析(KMeans聚类、数据分析)
  • 项目介绍
    • 数据
      • 数据维度概况
      • 数据13个维度介绍
    • 导入库,加载数据
    • 数据审查
    • 相关性分析
    • 数据处理
    • 建立模型
    • 聚类结果特征分析与展示
    • 数据结论

项目介绍

数据

假如公司投放广告的渠道很多,每个渠道的客户性质也可能不同,比如在优酷视频投广告和今日头条投放广告,效果可能会有差异。现在需要对广告效果分析实现有针对性的广告效果测量和优化工作。

本案例,通过各类广告渠道90天内额日均UV,平均注册率、平均搜索率、访问深度、平均停留时长、订单转化率、投放时间、素材类型、广告类型、合作方式、广告尺寸和广告卖点等特征,将渠道分类,找出每类渠道的重点特征,为加下来的业务讨论和数据分析提供支持。

数据维度概况

除了渠道唯一标识,共12个维度,889行,有缺失值,有异常值。

数据13个维度介绍

1、渠道代号:渠道唯一标识
2、日均UV:每天的独立访问量
3、平均注册率=日均注册用户数/平均每日访问量
4、平均搜索量:每个访问的搜索量
5、访问深度:总页面浏览量/平均每天的访问量
6、平均停留时长=总停留时长/平均每天的访问量
7、订单转化率=总订单数量/平均每天的访客量
8、投放时间:每个广告在外投放的天数
9、素材类型:‘jpg’ ‘swf’ ‘gif’ ‘sp’
10、广告类型:banner、tips、不确定、横幅、暂停
11、合作方式:‘roi’ ‘cpc’ ‘cpm’ ‘cpd’
12、广告尺寸:‘14040’ '308388’ ‘450300’ '60090’ ‘480360’ '960126’ ‘900120’ '390270’
13、广告卖点:打折、满减、满赠、秒杀、直降、满返

导入库,加载数据

import pandas as pd 
import numpy as np 
import matplotlib as mpl 
import matplotlib.pyplot as plt 
from sklearn.preprocessing import MinMaxScaler,OneHotEncoder 
from sklearn.metrics import silhouette_score # 导入轮廓系数指标
from sklearn.cluster import KMeans # KMeans模块
%matplotlib inline
## 设置属性防止中文乱码
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False

以上是加载库的国际惯例,OneHotEncoder是独热编码,如果一个类别特征有n个类别,将该变量按照类别分裂成N维新变量,包含则标记为1,否则为0,用N维特征表示原来的特征。

raw_data = pd.read_csv(r'./ad_performance.csv')
raw_data.head()
  1. raw_data = pd.read_csv(r'./ad_performance.csv'):这行代码使用Pandas库的read_csv()函数读取名为 “ad_performance.csv” 的CSV文件中的数据,并将数据加载到名为 raw_data 的DataFrame对象中。r'./ad_performance.csv' 是CSV文件的路径。r 表示使用原始字符串,防止反斜杠被转义。

  2. raw_data.head():这行代码使用DataFrame对象的head()方法查看DataFrame的前几行数据,默认显示前5行。这有助于了解数据的结构和格式。

数据审查

# 查看基本状态
raw_data.head(2)  # 打印输出前2条数据
raw_data.info()# 打印数据类型分布
raw_data.describe().round(2).T # 打印原始数据基本描述性信息
# 缺失值审查
na_cols = raw_data.isnull().any(axis=0)  # 查看每一列是否具有缺失值
na_cols
raw_data.isnull().sum().sort_values(ascending=False)# 查看具有缺失值的行总记录数
  1. raw_data.head(2):这行代码打印输出了数据的前两条记录,以便快速查看数据的样式和结构。

  2. raw_data.info():这行代码打印输出了数据集中每一列的数据类型以及非空值的数量,这有助于了解数据的完整性和类型。

  3. raw_data.describe().round(2).T:这行代码打印了数据集的基本描述性信息,包括计数、均值、标准差、最小值、25%分位数、中位数、75%分位数和最大值。.round(2)方法用于将描述性统计结果保留两位小数,.T方法用于转置结果,以便查看。

  4. na_cols = raw_data.isnull().any(axis=0):这行代码查看了每一列是否具有缺失值。raw_data.isnull()会生成一个布尔值的DataFrame,表示每个单元格是否为缺失值,.any(axis=0)会沿着列方向(axis=0)判断是否有至少一个True,即是否存在缺失值。

  5. na_cols:这行代码会输出一个布尔型Series,其中索引是DataFrame的列名,值为True表示该列存在缺失值,值为False表示该列没有缺失值。

  6. raw_data.isnull().sum().sort_values(ascending=False):这行代码查看了具有缺失值的列,并统计了每列的缺失值数量,并按照缺失值数量降序排列。.isnull()用于判断每个单元格是否为缺失值,.sum()对每列的缺失值数量进行求和,.sort_values(ascending=False)将结果按照缺失值数量进行降序排序。

相关性分析

# 相关性分析
raw_data.corr(numeric_only=True).round(2).T # 打印原始数据相关性信息
# 相关性可视化展示
import seaborn as sns 
corr = raw_data.corr().round(2)
sns.heatmap(corr,cmap='Reds',annot = True)
  1. raw_data.corr(numeric_only=True).round(2).T:这行代码计算了原始数据中数值型列之间的相关性,并将结果打印输出。.corr(numeric_only=True)表示只考虑数值型列之间的相关性,.round(2)将相关性系数保留两位小数,.T方法用于转置结果,以便查看。

  2. import seaborn as sns:这行代码导入了Seaborn库,用于绘制数据可视化图形。

  3. corr = raw_data.corr().round(2):这行代码计算了原始数据的相关性矩阵,并将相关性系数保留两位小数。

  4. sns.heatmap(corr,cmap='Reds',annot = True):这行代码绘制了一个热力图来展示相关性矩阵。heatmap()函数用于绘制热力图,corr是相关性矩阵,cmap='Reds'指定了颜色映射为红色调,annot = True表示在图中显示相关性系数的数值。

在这里插入图片描述

数据处理

数据了解的差不多了,我们开始时处理数据,把常规数据通过清洗、转换、规约、聚合、抽样等方式变成机器学习可以识别或者提升准确度的数据。

# 1 删除平均平均停留时间列
raw_data2 = raw_data.drop(['平均停留时间'],axis=1)
  1. raw_data2 = raw_data.drop(['平均停留时间'],axis=1):这行代码使用了DataFrame的drop()方法,通过指定'平均停留时间'列和axis=1参数,从原始数据中删除了’平均停留时间’列。删除操作不会在原始数据上进行,而是返回一个新的DataFrame对象,即raw_data2,其中不包含被删除的列。

类别变量的独热编码:

# 类别变量取值
cols=["素材类型","广告类型","合作方式","广告尺寸","广告卖点"]
for x in cols:
    data=raw_data2[x].unique()
    print("变量【{0}】的取值有:\n{1}".format(x,data))
    print("-·"*20)
  1. cols=["素材类型","广告类型","合作方式","广告尺寸","广告卖点"]:定义了一个列表 cols,其中包含了需要统计取值的类别变量的列名。

  2. for x in cols::这是一个循环语句,用于遍历列表 cols 中的每个元素。

  3. data=raw_data2[x].unique():这行代码获取了 DataFrame 中列 x(循环变量)的唯一取值,即去除重复后的取值列表。

  4. print("变量【{0}】的取值有:\n{1}".format(x,data)):这行代码使用字符串格式化,打印输出了变量 x 的取值列表。其中 {0}{1} 分别被循环变量 x 和取值列表 data 所替代。

  5. print("-·"*20):这行代码打印了一条分隔线,用于区分不同类别变量的取值统计结果。

# 字符串分类独热编码处理
cols = ['素材类型','广告类型','合作方式','广告尺寸','广告卖点'] 
model_ohe = OneHotEncoder(sparse=False)  # 建立OneHotEncode对象
ohe_matrix = model_ohe.fit_transform(raw_data2[cols])  # 直接转换
print(ohe_matrix[:2])
  1. cols = ['素材类型','广告类型','合作方式','广告尺寸','广告卖点']:定义了一个列表 cols,其中包含了需要进行独热编码处理的字符串分类变量的列名。

  2. model_ohe = OneHotEncoder(sparse=False):这行代码创建了一个OneHotEncoder对象 model_ohe,用于进行独热编码处理。sparse=False参数表示不生成稀疏矩阵,而是直接生成密集矩阵。

  3. ohe_matrix = model_ohe.fit_transform(raw_data2[cols]):这行代码对原始数据集 raw_data2 中的 cols 列进行独热编码处理,得到编码后的矩阵。fit_transform()方法将字符串分类变量转换为独热编码表示。

  4. print(ohe_matrix[:2]):这行代码打印输出了独热编码后的矩阵的前两行。这样做是为了查看编码结果是否符合预期。

# 用pandas的方法
ohe_matrix1=pd.get_dummies(raw_data2[cols])
ohe_matrix1.head(5)
  1. ohe_matrix1=pd.get_dummies(raw_data2[cols]):这行代码调用了 Pandas 的 get_dummies() 方法,对原始数据集 raw_data2 中的 cols 列进行独热编码处理。get_dummies() 方法会将指定列中的每个分类值都转换为一个独热编码的列,并生成一个新的 DataFrame 对象 ohe_matrix1

  2. ohe_matrix1.head(5):这行代码打印输出了独热编码后的结果的前 5 行。这样做是为了查看编码结果是否符合预期。

# 数据标准化
sacle_matrix = raw_data2.iloc[:, 1:7]  # 获得要转换的矩阵
model_scaler = MinMaxScaler()  # 建立MinMaxScaler模型对象
data_scaled = model_scaler.fit_transform(sacle_matrix)  # MinMaxScaler标准化处理
print(data_scaled.round(2))
  1. sacle_matrix = raw_data2.iloc[:, 1:7]:这行代码从原始数据集 raw_data2 中提取了需要进行标准化处理的数据子集。iloc[:, 1:7]表示选取所有行,以及第 2 到第 7 列的数据(Python中索引是从0开始的)。

  2. model_scaler = MinMaxScaler():这行代码创建了一个MinMaxScaler对象 model_scaler,用于进行最小-最大缩放标准化处理。

  3. data_scaled = model_scaler.fit_transform(sacle_matrix):这行代码使用 fit_transform() 方法对提取的数据子集 sacle_matrix 进行标准化处理,得到标准化后的结果。MinMaxScaler会将每列的数据缩放到指定的范围(默认为[0, 1]),并返回一个标准化后的NumPy数组 data_scaled

  4. print(data_scaled.round(2)):这行代码打印输出了标准化后的数据,使用 round(2) 方法保留两位小数。这样做是为了查看标准化后的数据是否符合预期。

# # 合并所有维度
X = np.hstack((data_scaled, ohe_matrix))
  1. np.hstack((data_scaled, ohe_matrix)):这行代码使用了 NumPy 的 hstack() 函数,将两个矩阵水平堆叠在一起。data_scaled 是经过标准化处理后的特征矩阵,ohe_matrix 是经过独热编码处理后的特征矩阵。水平堆叠意味着将两个矩阵按列连接起来。

  2. X = np.hstack((data_scaled, ohe_matrix)):这行代码将水平堆叠后的矩阵赋值给变量 X,这样就得到了合并后的特征矩阵 X,其中包含了标准化处理后的数据和独热编码处理后的数据。

建立模型

# 通过平均轮廓系数检验得到最佳KMeans聚类模型
score_list = list()  # 用来存储每个K下模型的平局轮廓系数
silhouette_int = -1  # 初始化的平均轮廓系数阀值
for n_clusters in range(2, 8):  # 遍历从2到5几个有限组
    model_kmeans = KMeans(n_clusters=n_clusters)  # 建立聚类模型对象
    labels_tmp = model_kmeans.fit_predict(X)  # 训练聚类模型
    silhouette_tmp = silhouette_score(X, labels_tmp)  # 得到每个K下的平均轮廓系数
    if silhouette_tmp > silhouette_int:  # 如果平均轮廓系数更高
        best_k = n_clusters  # 保存K将最好的K存储下来
        silhouette_int = silhouette_tmp  # 保存平均轮廓得分
        best_kmeans = model_kmeans  # 保存模型实例对象
        cluster_labels_k = labels_tmp  # 保存聚类标签
    score_list.append([n_clusters, silhouette_tmp])  # 将每次K及其得分追加到列表
print('{:*^60}'.format('K值对应的轮廓系数:'))
print(np.array(score_list))  # 打印输出所有K下的详细得分
print('最优的K值是:{0} \n对应的轮廓系数是:{1}'.format(best_k, silhouette_int))

总体思想(评价指标)还是怎么聚才能使得簇内距离足够小,簇与簇之间平均距离足够大来评判。

  1. score_list = list():创建一个空列表,用于存储每个K值下模型的平均轮廓系数。

  2. silhouette_int = -1:初始化平均轮廓系数的阈值为-1。

  3. for n_clusters in range(2, 8)::循环遍历从2到7的整数,这些整数代表了KMeans聚类模型的聚类数。

  4. model_kmeans = KMeans(n_clusters=n_clusters):创建一个KMeans聚类模型对象,其中n_clusters参数表示要创建的聚类数。

  5. labels_tmp = model_kmeans.fit_predict(X):利用输入数据 X 对KMeans模型进行训练,并预测每个样本的聚类标签。

  6. silhouette_tmp = silhouette_score(X, labels_tmp):计算当前K值下的平均轮廓系数,用来衡量聚类效果的好坏。

  7. if silhouette_tmp > silhouette_int::如果当前K值下的平均轮廓系数大于之前的最高值。

  8. best_k = n_clusters:更新最佳的K值为当前K值。

  9. silhouette_int = silhouette_tmp:更新最高的平均轮廓系数为当前轮廓系数。

  10. best_kmeans = model_kmeans:保存当前最佳的KMeans聚类模型对象。

  11. cluster_labels_k = labels_tmp:保存当前最佳的聚类标签。

  12. score_list.append([n_clusters, silhouette_tmp]):将当前K值和对应的平均轮廓系数追加到列表score_list中。

  13. print('{:*^60}'.format('K值对应的轮廓系数:')):打印输出一个60个星号的分割线。

  14. print(np.array(score_list)):打印输出所有K值及其对应的平均轮廓系数。

  15. print('最优的K值是:{0} \n对应的轮廓系数是:{1}'.format(best_k, silhouette_int)):打印输出最佳的K值和对应的平均轮廓系数。

聚类结果特征分析与展示

通过上面模型,我们其实给每个观测(样本)打了个标签clusters,即他属于4类中的哪一类:

# 将原始数据与聚类标签整合
cluster_labels = pd.DataFrame(cluster_labels_k, columns=['clusters'])  # 获得训练集下的标签信息
merge_data = pd.concat((raw_data2, cluster_labels), axis=1)  # 将原始处理过的数据跟聚类标签整合
merge_data.head()
  1. cluster_labels = pd.DataFrame(cluster_labels_k, columns=['clusters']):这行代码创建了一个名为 cluster_labels 的DataFrame对象,其中包含了聚类模型预测得到的聚类标签信息。cluster_labels_k 是之前代码中得到的聚类标签数据,columns=['clusters'] 指定了DataFrame的列名为’clusters’。

  2. merge_data = pd.concat((raw_data2, cluster_labels), axis=1):这行代码使用了 Pandas 的 concat() 函数,将原始处理过的数据 raw_data2 与聚类标签数据 cluster_labels 沿着列方向(axis=1)进行合并。合并后的结果赋值给变量 merge_data

  3. merge_data.head():这行代码打印输出了合并后的DataFrame的前几行数据。这样做是为了查看整合后的数据是否符合预期。

然后看看,每个类别下的样本数量和占比情况:

# 计算每个聚类类别下的样本量和样本占比
clustering_count = pd.DataFrame(merge_data['渠道代号'].groupby(merge_data['clusters']).count()).T.rename({'渠道代号': 'counts'})  # 计算每个聚类类别的样本量
clustering_ratio = (clustering_count / len(merge_data)).round(2).rename({'counts': 'percentage'})  # 计算每个聚类类别的样本量占比
print(clustering_count)
print("#"*30)
print(clustering_ratio)
  1. clustering_count = pd.DataFrame(merge_data['渠道代号'].groupby(merge_data['clusters']).count()).T.rename({'渠道代号': 'counts'}):这行代码首先使用 Pandas 的 groupby() 函数按照聚类标签 clusters渠道代号 这一列进行分组,然后对每个组计算该列的计数。结果是一个包含每个聚类类别下的样本量的 Series 对象。接着使用 pd.DataFrame() 将其转换为 DataFrame,并进行转置(.T)操作,以使行和列对调。最后使用 rename() 函数将列名 渠道代号 更改为 counts,以反映其含义。

  2. clustering_ratio = (clustering_count / len(merge_data)).round(2).rename({'counts': 'percentage'}):这行代码计算每个聚类类别的样本量占比。首先将每个聚类类别的样本量除以总样本量,然后使用 round(2) 方法将结果保留两位小数。接着使用 rename() 函数将列名 counts 更改为 percentage,以反映其含义。

  3. print(clustering_count):打印输出每个聚类类别下的样本量。

  4. print("#"*30):打印输出一个包含30个 ‘#’ 字符的分隔线。

  5. print(clustering_ratio):打印输出每个聚类类别的样本量占比。

每个类别内部最显著的特征:

# 计算各个聚类类别内部最显著特征值
cluster_features = []  # 空列表,用于存储最终合并后的所有特征信息
for line in range(best_k):  # 读取每个类索引
    label_data = merge_data[merge_data['clusters'] == line]  # 获得特定类的数据

    part1_data = label_data.iloc[:, 1:7]  # 获得数值型数据特征
    part1_desc = part1_data.describe().round(3)  # 得到数值型特征的描述性统计信息
    merge_data1 = part1_desc.iloc[2, :]  # 得到数值型特征的均值

    part2_data = label_data.iloc[:, 7:-1]  # 获得字符串型数据特征
    part2_desc = part2_data.describe(include='all')  # 获得字符串型数据特征的描述性统计信息
    merge_data2 = part2_desc.iloc[2, :]  # 获得字符串型数据特征的最频繁值

    merge_line = pd.concat((merge_data1, merge_data2), axis=0)  # 将数值型和字符串型典型特征沿行合并
    cluster_features.append(merge_line)  # 将每个类别下的数据特征追加到列表

#  输出完整的类别特征信息
cluster_pd = pd.DataFrame(cluster_features).T  # 将列表转化为矩阵
print('{:*^60}'.format('每个类别主要的特征:'))
all_cluster_set = pd.concat((clustering_count, clustering_ratio, cluster_pd),axis=0)  # 将每个聚类类别的所有信息合并
all_cluster_set
  1. cluster_features = []:创建一个空列表,用于存储每个聚类类别内部最显著的特征值。

  2. for line in range(best_k)::循环遍历每个聚类类别的索引。

  3. label_data = merge_data[merge_data['clusters'] == line]:获取特定聚类类别的数据,即通过筛选出'clusters'列值等于当前索引值的行。

  4. part1_data = label_data.iloc[:, 1:7]part2_data = label_data.iloc[:, 7:-1]:分别提取数值型特征和字符串型特征的数据子集。

  5. part1_desc = part1_data.describe().round(3)part2_desc = part2_data.describe(include='all'):分别计算数值型特征和字符串型特征的描述性统计信息。

  6. merge_data1 = part1_desc.iloc[2, :]merge_data2 = part2_desc.iloc[2, :]:分别获取数值型特征和字符串型特征的均值(数值型特征)或最频繁值(字符串型特征)。

  7. merge_line = pd.concat((merge_data1, merge_data2), axis=0):将数值型特征和字符串型特征沿行方向合并为一个Series对象。

  8. cluster_features.append(merge_line):将每个类别下的数据特征追加到列表cluster_features中。

  9. cluster_pd = pd.DataFrame(cluster_features).T:将列表cluster_features转换为DataFrame对象,转置以便特征信息按列排列。

  10. all_cluster_set = pd.concat((clustering_count, clustering_ratio, cluster_pd),axis=0):将聚类类别的样本量、样本占比和主要特征值信息沿着行方向合并为一个DataFrame对象all_cluster_set

  11. print('{:*^60}'.format('每个类别主要的特征:')):打印输出一个包含60个星号的标题行,用于分隔不同部分的输出。

  12. print(all_cluster_set):打印输出合并后的聚类类别的所有信息,包括样本量、样本占比和主要特征值信息。

图形化输出:

#各类别数据预处理
num_sets = cluster_pd.iloc[:6, :].T.astype(np.float64)  # 获取要展示的数据
num_sets_max_min = model_scaler.fit_transform(num_sets)  # 获得标准化后的数据
print(num_sets)
print('-'*20)
print(num_sets_max_min)
  1. num_sets = cluster_pd.iloc[:6, :].T.astype(np.float64):这行代码从合并后的聚类类别特征数据 cluster_pd 中提取了前6行(即数值型特征)的转置,并将其转换为np.float64类型的数据。这样做是为了将数据按列排列,方便后续处理。

  2. num_sets_max_min = model_scaler.fit_transform(num_sets):这行代码利用之前创建的 MinMaxScaler 对象 model_scaler 对数值型特征数据进行标准化处理。使用 fit_transform() 方法对数据进行标准化,将数据缩放到[0, 1]的范围内。

  3. print(num_sets):打印输出原始的数值型特征数据,用于查看。

  4. print('-'*20):打印输出一行分隔线。

  5. print(num_sets_max_min):打印输出标准化后的数值型特征数据,用于查看。

# 画图
fig = plt.figure(figsize=(7,7))  # 建立画布
ax = fig.add_subplot(111, polar=True)  # 增加子网格,注意polar参数
labels = np.array(merge_data1.index)  # 设置要展示的数据标签
cor_list = ['g', 'r', 'y', 'b']  # 定义不同类别的颜色
angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False)  # 计算各个区间的角度
angles = np.concatenate((angles, [angles[0]]))  # 建立相同首尾字段以便于闭合
# 画雷达图
for i in range(len(num_sets)):  # 循环每个类别
    data_tmp = num_sets_max_min[i, :]  # 获得对应类数据
    data = np.concatenate((data_tmp, [data_tmp[0]]))  # 建立相同首尾字段以便于闭合
    ax.plot(angles, data, 'o-', c=cor_list[i], label="第%d类渠道"%(i))  # 画线
    ax.fill(angles, data,alpha=0.8)
    
# 设置图像显示格式
print(angles)
print(labels)

ax.set_thetagrids(angles[0:-1] * 180 / np.pi, labels, fontproperties="SimHei")  # 设置极坐标轴
ax.set_title("各聚类类别显著特征对比", fontproperties="SimHei")  # 设置标题放置
ax.set_rlim(-0.2, 1.2)  # 设置坐标轴尺度范围
plt.legend(loc="upper right" ,bbox_to_anchor=(1.2,1.0))  # 设置图例位置
  1. fig = plt.figure(figsize=(7,7)):创建一个大小为7x7的画布。

  2. ax = fig.add_subplot(111, polar=True):在画布上添加一个极坐标子网格,参数polar=True表示使用极坐标。

  3. labels = np.array(merge_data1.index):将聚类类别的特征名称作为要展示的数据标签。

  4. cor_list = ['g', 'r', 'y', 'b']:定义不同类别的颜色。

  5. angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False):计算各个特征区间的角度。

  6. angles = np.concatenate((angles, [angles[0]])):建立相同首尾字段以便于闭合。

  7. for i in range(len(num_sets))::遍历每个聚类类别。

  8. data_tmp = num_sets_max_min[i, :]:获取当前聚类类别对应的标准化后的特征数据。

  9. data = np.concatenate((data_tmp, [data_tmp[0]])):建立相同首尾字段以便于闭合。

  10. ax.plot(angles, data, 'o-', c=cor_list[i], label="第%d类渠道"%(i)):绘制雷达图,表示各个特征在当前聚类类别下的数值,使用不同颜色区分不同类别。

  11. ax.fill(angles, data,alpha=0.8):填充雷达图的闭合区域,以加强可视化效果。

  12. ax.set_thetagrids(angles[0:-1] * 180 / np.pi, labels, fontproperties="SimHei"):设置极坐标轴的刻度标签和标签文字。

  13. ax.set_title("各聚类类别显著特征对比", fontproperties="SimHei"):设置雷达图的标题。

  14. ax.set_rlim(-0.2, 1.2):设置雷达图的坐标轴尺度范围。

  15. plt.legend(loc="upper right" ,bbox_to_anchor=(1.2,1.0)):设置图例的位置,将图例放在图的右上角。

在这里插入图片描述

数据结论

从案例结果来看,所有的渠道被分为4各类别,每个类别的样本量分别为:154、313、349 、73,对应占比分别为:17%、35%、39%、8%。

通过雷达图可以清楚的知道:

类别1(索引为2类的渠道) 这类广告媒体除了访问深度和投放时间较高,其他属性较低,因此这类广告媒体效果质量较差,并且占到39%,因此这类是主题渠道之一。 业务部门要考虑他的实际投放价值。

类别2(索引为1类的渠道) 这类广告媒体除了访问深度略差,在平均搜索量、日均UV、订单转化率等广告效果指标上表现良好,是一类综合效果较好的渠道。 但是日均UV是短板,较低。无法给企业带来大量的流量以及新用户,这类广告的特质适合用户转化,尤其是有关订单的转化提升。

类别3(索引为0类的渠道) 这类广告媒体的显著特征是日均UV和注册率较高,其“引流”和“拉新”效果好,可以在广告媒体中定位为引流角色。 符合“广而告之”的诉求,适合“拉新”使用。

类别4(索引为3类的渠道) 这类渠道各方面特征都不明显,各个流量质量和流量数量的指标均处于“中等”层次。不突出但是均衡,考虑在各场景下可以考虑在这个渠道投放广告。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/510825.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ceph学习 - 1.存储知识

文章目录 1.存储基础1.1 基础知识1.1.1 存储基础1.1.2 存储使用 1.2 文件系统1.2.1 简介1.2.2 数据存储1.2.3 存储应用的基本方式1.2.4 文件存储 1.3 小结 1.存储基础 学习目标:这一节,我们从基础知识、文件系统、小节三个方面来学习。 1.1 基础知识 1.…

day01 51单片机

51单片机学习 1 51单片机概述 1.1 51单片机简介 目前使用的51单片机一般是宏晶STC89系列,这其中流传最广的版本,也是我们课程的主角,就是STC89C52RC。 1.2 命名规则 1.3 单片机最小应用系统 2 点亮LED灯 2.1 硬件原理图 这个原理图非常简单,VCC接保护电阻R1,串联LED1最…

IOTX:未来市场爆发点的RWA协议?DePIN赛道被低估的龙头

从基本面来看,IoTeX的目标是创建一个连接的世界,在这个世界中,每个人都能控制自己的数据、设备和身份。通过区块链技术,IoTeX旨在解锁智能设备和数据的潜力,支持新一代的现实世界Dapp和数字资产的发展。IOTX始终致力于…

个性化内容的力量:Kompas.ai如何帮你定制内容

在当今的数字化营销环境中,个性化内容已经成为品牌与消费者建立深层次联系的关键。个性化内容不仅能够更好地满足用户的需求,还能够加深用户的品牌体验,从而提高用户满意度和忠诚度。本文将深入探讨个性化内容在提升用户参与度和忠诚度方面的…

Incus:新一代容器与虚拟机编排管理引擎

Incus是什么? Incus是一个用于编排管理应用型容器、系统型容器及虚拟机实例的管理工具。它是对 Canonical LXD 的继承与发展,引入了更多的存储驱动支持。 Incus项目的产品地址:Linux Containers - Incus - Introduction 在 LXC-Incus 项目…

Java练习

这个练习我用到了继承,多态和封装。 1.继承: Animal 类是一个抽象类,它有两个子类 Dog 和 Cat。 Dog 和 Cat 分别继承自 Animal 类,因此它们可以使用 Animal 类中定义的属性和方法,同时也可以有自己特有的属性和方法。…

鸿蒙OS元服务开发:【(Stage模型)学习窗口沉浸式能力】

一、体验窗口沉浸式能力说明 在看视频、玩游戏等场景下,用户往往希望隐藏状态栏、导航栏等不必要的系统窗口,从而获得更佳的沉浸式体验。此时可以借助窗口沉浸式能力(窗口沉浸式能力都是针对应用主窗口而言的),达到预…

基于springboot+vue+Mysql的教学视频点播系统

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…

pymc,一个灵活的的 Python 概率编程库!

目录 前言 安装与配置 概率模型 贝叶斯推断 概率分布 蒙特卡罗采样 贝叶斯网络 实例分析 PyMC库的应用场景 1. 概率建模 2. 时间序列分析 3. 模式识别 总结 前言 大家好,今天为大家分享一个超强的 Python 库 - pymc Github地址:https://gith…

黄金票据攻击

黄金票据攻击——域内横向移动技术 一、黄金票据攻击介绍: 黄金票据攻击是一种滥用Kerberos身份认证协议的攻击方式,它允许攻击者伪造域控krbtgt用户的TGT(Ticket-Granting Ticket)。通过这种方法,攻击者可以生成有效…

怎么禁止特定程序运行

计算机已经成为了人们日常生活和工作中不可或缺的工具。 然而,随着计算机应用的广泛化,如何管理和控制计算机上的程序运行也成为了一个亟待解决的问题。 特别是在企业、学校或一些需要严格控制计算机使用环境的场所。 为什么要禁止特定程序运行&#x…

Catcatcat【杂项 攻防世界】

知识点: strings 命令 打印文件中可以打印的字符,可以是任意文件grep flag 过滤出文件中的flag关键字rabbit加密 深入了解Rabbit加密技术:原理、实现与应用-CSDN博客对称加密算法需要密钥,也可不设置数据开头固定:U2F…

6.8物联网RK3399项目开发实录-驱动开发之RTC实时时钟的使用(wulianjishu666)

90款行业常用传感器单片机程序及资料【stm32,stc89c52,arduino适用】 链接:https://pan.baidu.com/s/1M3u8lcznKuXfN8NRoLYtTA?pwdc53f RTC 使用 简介 AIO-3399J 开发板上有 一个集成于 RK808 上的RTC(Real Time Clock),主要功能有时钟&#xff0c…

【OpenCV-颜色空间】

OpenCV-颜色空间 ■ RGB■ BGR■ HSV■ HSL■ HUE■ YUV ■ RGB ■ BGR BGR 就是RGB R和B调换位置。 OpenCV 默认使用BGR ■ HSV ■ HSL ■ HUE ■ YUV

【高校科研动态】贵州师大博士生封清为一作在J. Clean. Prod.发文:中国扶贫搬迁对生态影响的量化研究——以贵州省为例

目录 1.文章简介 2.主要研究内容 3.文章引用 1.文章简介 论文名称:Quantifying the extent of ecological impact from Chinas poverty alleviation relocation program: A case study in Guizhou Province 第一作者及通讯作者:封清&#…

代码随想录第28天 | 93.复原IP地址 、 78.子集 、 90.子集II

一、前言: 参考文献:代码随想录 今天的主题内容是回溯算法,这一章的干货很多,我需要慢慢的品味,不单单只是表象,还需要研究深层原理。 二、复原IP地址 1、思路: (1)…

反射的学习

反射的作用: 1.获取一个类里面的所有信息,获取到之后,在执行其他的业务逻辑 2.结合配置文件,动态的创建对象并调用方法

OpenHarmony实战:轻量级系统之启动恢复子系统移植

启动恢复子系统负责在内核启动之后到应用启动之前的系统关键进程和服务的启动过程的功能。 移植指导 针对轻量系统主要提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用bootstrap标识的入口函数,并启动系统服务。 适配完成后,调用…

Node.js------Express

◆ 能够使用 express.static( ) 快 速 托 管 静 态 资 源◆ 能够使用 express 路 由 精 简 项 目 结 构◆ 能够使用常见的 express 中间件◆ 能够使用 express 创建API接口◆ 能够在 express 中启用cors跨域资源共享 一.初识Express 1.Express 简介 官方给出的概念&#xff…

Micron FY24 Q2业绩强劲,凭内存实现翻盘

根据TechInsights数据显示,美光科技24财年第二季度业绩强劲,公司通过技术创新和产能优化,成功抓住了AI服务器和其他高性能应用带来的市场需求增长机遇。尽管短期内面临供应紧张的问题,但美光通过加大研发投入和产能转换力度&#…