给大家写一个详细的 用户画像中用Kmeans算法来实现RFM指标计算步骤

# 使用机器学习算法实现rfm
from utils.base import BasicTag
from pyspark.sql import SparkSession,functions as F
from pyspark.sql.types import *
from pyspark.ml.feature import VectorAssembler
from pyspark.ml.clustering import KMeans

class RFMTag(BasicTag):

    def make_tag(self):
        rule_dict = self.data_dict
        # 1-计算获取RFM的值
        # 消费周期计算
        recency = F.datediff(F.current_date(), F.from_unixtime(F.max('finishtime'))).alias('diff_dt').alias('recency')
        # 订单量
        frequency = F.countDistinct('ordersn').alias('frequency')
        # 订单金额
        monetary = F.sum('orderamount').alias('monetary')
        df_rfm = self.df_es.groupby('memberid').agg(recency,frequency,monetary)

        # 2-根据计算的结果,将数据划分5个等级进行打分
# -----------------------------R数据打分----------------------------------------------------------------------------------
        # 2-1 特征工程将数据转为向量(只有转化为坐标向量(VectorAssembler),才能在坐标轴上计算方向及两点之间的距离,再求平均距离)
        v_r = VectorAssembler(inputCols=['recency'],outputCol='v_r')
        # 添加转化数据,将上面订单金额加入进行转化
        df_r_fit = v_r.transform(df_rfm)

        # 2-2 使用kmeas算法打分,
        #     k参数负责划分几个分数段;
        #     featuresCol负责传入向量值用于聚类的特征向量的列名;
        #     predictionCol 用于存储聚类结果的列名。KMeans算法会在训练数据上进行聚类分析,并将每个数据点分配到一个聚类。这个聚类结果会存储在predictionCol指定的列中。
        #+---+-----------------+                                    +---+-----------------------+
        #|id |        v_r      |                                    |id |        v_r      | k_r |
        #+---+-----------------+                                    +---+-----------------+-----+
        #| 1 | [1.0, 2.0, 3.0] |          执行KMeans聚类后:          | 1 | [1.0, 2.0, 3.0] |  0  |
        #| 2 | [4.0, 5.0, 6.0] |    ————————————————————————>       | 2 | [4.0, 5.0, 6.0] |  1  |
        #| 3 | [7.0, 8.0, 9.0] |                                    | 3 | [7.0, 8.0, 9.0] |  2  |
        #| 4 |[10.0, 11.0, 12.0]|                                   | 4 |[10.0, 11.0, 12.0]|  3 |
        kmeans = KMeans(k=5,featuresCol='v_r',predictionCol='k_r')

        # 添加数据----kmeans.fit( )用于训练模型,训练完生成一个KMeans模型对象k_r_fit
        k_r_fit = kmeans.fit(df_r_fit)

        # 转化数据,对训练结果进行预测,将预测结果添加到数据框:df_k_r中
        df_k_r = k_r_fit.transform(df_r_fit)
        df_k_r.show()

        # 计算k值中心判断k值的大小--clusterCenters()获取每个聚类的中心点(质心),存储在cluster变量中。
        cluster = k_r_fit.clusterCenters()

        # 遍历k值(质点)中心,计算k值的和
        # cluster_dict = {}:创建一个空字典,用于存储每个聚类中心点的索引和其特征值的和。
        # enumerate:是 Python 的一个内置函数,用于在遍历可迭代对象(如列表、元组、字符串等)时,同时获取每个元素的索引和值。它返回一个枚举对象,该对象生成一系列包含索引和值的元组。
        # 示例列表:
        #------------------------------------------+
        #   fruits = ['apple', 'banana', 'cherry'] |
        #   #使用 enumerate 进行遍历                 |
        #   for index, value in enumerate(fruits): |
        #   rint(index, value)                     |
        #--------输出------------------------------+
        #   0 apple                               |
        #   1 banana                              |
        #   2 cherry                              |
        #-----------------------------------------+
        cluster_dict = {}
        for i, v in enumerate(cluster):
            cluster_dict[i] = sum(v)
        print(cluster_dict)  # 输出结果:{0: 1445.0, 1: 1446.0, 2: 1447.0}

        # 中心点排序,对cluster_dict按特征值的和进行升序排序--并强制类型转化为字典格式
        cluster_dict_sort = dict(sorted(cluster_dict.items(), key=lambda x: x[1]))

        # 对k中心替换大小
        # count = 0:初始化计数器。
        # for k, v in cluster_dict_sort.items():遍历排序后的字典cluster_dict_sort。
        # cluster_dict_sort[k] = count:将排序后的中心点索引替换为从0开始的递增值。
        # count += 1:计数器递增。然后使用cluster_dict_sort[k] 进行值的替换
        count = 0
        for k, v in cluster_dict_sort.items():
            cluster_dict_sort[k] = count
            count += 1

        # 替换原来df中的k值编号
        @F.udf(returnType=IntegerType())
        def repace_data(k):
            return cluster_dict_sort.get(k)

        df_replace_r = df_k_r.select(df_k_r.memberid,df_k_r.recency,df_k_r.frequency,df_k_r.monetary,repace_data('k_r').alias('k_r'))

#-----------------------------F数据打分----------------------------------------------------------------------------------
        # 2-1 特征工程将数据转为向量
        f_r = VectorAssembler(inputCols=['frequency'], outputCol='f_r')
        # 添加转化数据
        df_f_fit = f_r.transform(df_replace_r)

        # 2-2 kmeas算法打分
        kmeans = KMeans(k=5, featuresCol='f_r', predictionCol='k_f')
        # 添加数据
        f_r_fit = kmeans.fit(df_f_fit)
        # 转化数据
        df_f_r = f_r_fit.transform(df_f_fit)

        # 计算k值中心判断k值的大小
        cluster = f_r_fit.clusterCenters()

        # 遍历k值中心,计算k值的和
        cluster_dict = {}
        for i, v in enumerate(cluster):
            cluster_dict[i] = sum(v)

        # 中心点排序
        cluster_dict_sort = dict(sorted(cluster_dict.items(), key=lambda x: x[1]))

        # 对k中心替换大小
        count = 0
        for k, v in cluster_dict_sort.items():
            cluster_dict_sort[k] = count
            count += 1

        # 替换原来df中的k值编号
        @F.udf(returnType=IntegerType())
        def repace_data1(k):
            return cluster_dict_sort.get(k)

        df_replace_f = df_f_r.select(df_f_r.memberid, df_f_r.recency, df_f_r.frequency, df_f_r.monetary,df_f_r.k_r,
                      repace_data1('k_f').alias('k_f'))

        print('F计算完成')
# -----------------------------M数据打分----------------------------------------------------------------------------------
        # 2-1 特征工程将数据转为向量
        # TODO:inputColss输入字段修改  outputCol字段修改
        m_r = VectorAssembler(inputCols=['monetary'], outputCol='m_r')
        # 添加转化数据
        # TODO: 替换上一步的df数据
        df_f_fit = m_r.transform(df_replace_f)

        # 2-2 kmeas算法打分
        # TODO:inputColss输入字段修改  outputCol字段修改
        kmeans = KMeans(k=5, featuresCol='m_r', predictionCol='k_m')
        # 添加数据
        f_r_fit = kmeans.fit(df_f_fit)
        # 转化数据
        df_f_r = f_r_fit.transform(df_f_fit)
        df_f_r.show()
        print('M评分')

        # 计算k值中心判断k值的大小
        cluster = f_r_fit.clusterCenters()

        # 遍历k值中心,计算k值的和
        cluster_dict = {}
        for i, v in enumerate(cluster):
            cluster_dict[i] = sum(v)

        # 中心点排序
        cluster_dict_sort = dict(sorted(cluster_dict.items(), key=lambda x: x[1]))

        # 对k中心替换大小
        count = 0
        for k, v in cluster_dict_sort.items():
            cluster_dict_sort[k] = count
            count += 1

        # 替换原来df中的k值编号
        @F.udf(returnType=IntegerType())
        def repace_data2(k):
            return cluster_dict_sort.get(k)
        # TODO:
        df_replace_m = df_f_r.select(df_f_r.memberid, df_f_r.recency, df_f_r.frequency, df_f_r.monetary, df_f_r.k_r, df_f_r.k_f,
                                     repace_data2('k_m').alias('k_m'))

        df_replace_m.show()
        print('M计算完成')

        # 3-计算所有用户的平均打分--结果为一行数据
        df_rfm_score_avg = df_replace_m.select(F.avg('k_r').alias('r_avg'),F.avg('k_f').alias('f_avg'),F.avg('k_m').alias('m_avg'))
        # +-----+-----+-----+
        # |r_avg|f_avg|m_avg|
        # +-----+-----+-----+
        # | 2.0 | 3.0 | 4.0 |
        # +-----+-----+-----+
        # 将平均分转为row对象可以获第一行取值(实际上只有一行)
        # row 是一个 Row 对象,它允许你像访问属性一样访问列值。
        row = df_rfm_score_avg.first()

        # 4-通过平均值判断rfm的高低
        df_rfm_num =  df_replace_m.select(
            df_replace_m.memberid,
            # 大于为1  否则为0
            F.when(df_replace_m.k_r >= row['r_avg'],1).otherwise(0).alias('rn'),
            F.when(df_replace_m.k_f > row['f_avg'],1).otherwise(0).alias('fn'),
            F.when(df_replace_m.k_m > row['m_avg'],1).otherwise(0).alias('mn'),
        )

        # 5-标签匹配
        # df_rfm_num 是一个包含 RFM 分数的 DataFrame。
        # select 方法选择了 memberid 列和通过 concat 方法连接的 RFM 分数(即 rn、fn、mn)。
        # F.concat 将 R、F、M 分数转化为字符串并连接成一个新的字符串。
        # 最后,alias('rfm') 为这个新字符串列命名为 rfm
        df_rfm_str = (df_rfm_num.select
                        (
                            df_rfm_num.memberid,
                            F.concat  # F.concat 将 R、F、M 分数转化为字符串并连接成一个新的字符串。并且alias('rfm') 为这个新字符串列命名为 rfm
                                (
                                  df_rfm_num.rn.cast('string'),
                                  df_rfm_num.fn.cast('string'),
                                  df_rfm_num.mn.cast('string')).alias('rfm'
                                )
                        )
                     )
        df_rfm_str.show()
        # 这是一个用户定义函数(UDF),用于根据 rule_dict 字典将 RFM 字符串映射到相应的标签。
        # @F.udf(returnType=StringType()) 装饰器用于将 Python 函数转化为 PySpark UDF,并指定返回类型为 StringType()。
        @F.udf(returnType=StringType())
        def match(data):
            return rule_dict.get(data)
        # 应用 match 函数并创建新 DataFrame:
        self.df_new_tag = (df_rfm_str.select
                                    (
                                        df_rfm_str.memberid.alias('userID'),
                                        match(df_rfm_str.rfm).alias('tagsID')
                                    )
                            )

# 创建对象
ss = SparkSession.builder.config('spark.sql.shuffle.partitions','6').getOrCreate()
rfm = RFMTag()
# 执行
rfm.action('RFM', ss, 'tfec_tags', 'tbl_basic_tag')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 下面是一段实现Kmeans聚类算法的Python代码:from sklearn.cluster import KMeans import numpy as np# 设定K的值 k = 3 # 生成训练数据 X = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]]) # 构建模型 kmeans = KMeans(n_clusters=k) # 训练模型 kmeans.fit(X) # 输出聚类中心 print(kmeans.cluster_centers_) # 输出预测结果 print(kmeans.labels_) ### 回答2: Kmeans是一种常用的聚类算法,主要用于将数据点划分为K个簇。下面是一个用Python编的简单的Kmeans聚类算法示例: ``` python import numpy as np def kmeans(data, k, max_iter=100): # 随机初始化K个中心点 centers = data[np.random.choice(range(len(data)), size=k, replace=False)] for _ in range(max_iter): # 计算每个数据点到各个中心点的距离 distances = np.linalg.norm(data[:, np.newaxis] - centers, axis=2) # 根据距离将数据点分配到最近的中心点 labels = np.argmin(distances, axis=1) # 更新中心点位置为所属簇的均值 for i in range(k): centers[i] = np.mean(data[labels == i], axis=0) return labels # 测试代码 data = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]]) k = 2 labels = kmeans(data, k) print(labels) # 输出每个数据点所属的簇索引 ``` 以上代码实现一个简单的Kmeans聚类算法。首先,随机选择K个数据点作为初始的中心点,然后通过循环迭代的方式,计算每个数据点到各个中心点的距离,将其分配到最近的中心点的簇中,并更新中心点位置为所属簇的均值。最终返回每个数据点所属的簇索引。 上述示例代码中,我们使用了numpy库来进行矩阵计算,并将数据点表示为一个二维的numpy数组。您可以根据自己的需要对代码进行修改和扩展,例如添加计算簇内误差等功能。 ### 回答3: K均值聚类算法是一种常用的无监督学习算法,适用于将数据集分成多个互不重叠的簇。下面是一个用Python编的简单K均值聚类算法的示例: ```python import numpy as np def kmeans(data, k, max_iter): centroids = init_centroids(data, k) for _ in range(max_iter): clusters = [[] for _ in range(k)] # 根据当前的质心将样本分配到对应的簇中 for sample in data: cluster_idx = assign_cluster(sample, centroids) clusters[cluster_idx].append(sample) # 根据当前分配的簇重新计算质心 new_centroids = [np.mean(cluster, axis=0) for cluster in clusters] # 判断质心是否发生变化,如果没有则停止迭代 if np.allclose(centroids, new_centroids): break centroids = new_centroids return centroids, clusters def init_centroids(data, k): # 从数据集中随机选择k个样本作为初始质心 indices = np.random.choice(range(len(data)), size=k, replace=False) centroids = data[indices] return centroids def assign_cluster(sample, centroids): # 计算样本到各个质心的距离,并返回距离最近的质心的索引 distances = np.linalg.norm(sample - centroids, axis=1) return np.argmin(distances) # 示例用法 data = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]) k = 2 max_iter = 10 centroids, clusters = kmeans(data, k, max_iter) print("质心:", centroids) print("簇划分:", clusters) ``` 该示例代码使用Numpy库实现了K均值聚类算法。输入数据存储在一个NumPy数组中,其中每一行代表一个样本。函数`kmeans`接受三个参数:数据集、簇的数量和最大迭代次数。该函数返回计算得到的质心和簇划分结果。 在算法实现中,首先使用`init_centroids`函数从数据集中随机选择k个样本作为初始质心。然后,根据当前的质心将所有样本分配到对应的簇中,通过调用`assign_cluster`函数计算样本到各个质心的距离,并将样本分配到距离最近的质心所在的簇中。接着,根据当前分配的簇重新计算质心,通过求每个簇中样本的均值来更新质心的位置。最后,判断质心是否发生变化,如果没有变化则停止迭代,否则继续进行下一轮迭代。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值