新版流量池服务端提交
This commit is contained in:
@@ -46,14 +46,19 @@ class RFMController extends BaseController
|
||||
$weightM = isset($config['weight_M']) ? (float)$config['weight_M'] : self::DEFAULT_WEIGHT_M;
|
||||
$abnormalMoneyRatio = isset($config['abnormal_money_ratio']) ? (float)$config['abnormal_money_ratio'] : self::DEFAULT_ABNORMAL_MONEY_RATIO;
|
||||
$scoreScale = isset($config['score_scale']) ? (int)$config['score_scale'] : self::DEFAULT_SCORE_SCALE;
|
||||
$missingStrategy = isset($config['missing_strategy']) ? $config['missing_strategy'] : 'score_1';
|
||||
$missingStrategy = isset($config['missing_strategy']) ? $confi961102'] : 'score_1';
|
||||
|
||||
// 权重归一化处理
|
||||
$weightSum = $weightR + $weightF + $weightM;
|
||||
if ($weightSum != 1.0) {
|
||||
if ($weightSum != 1.0 && $weightSum > 0) {
|
||||
$weightR = $weightR / $weightSum;
|
||||
$weightF = $weightF / $weightSum;
|
||||
$weightM = $weightM / $weightSum;
|
||||
} elseif ($weightSum == 0) {
|
||||
// 如果权重全为0,使用默认权重
|
||||
$weightR = self::DEFAULT_WEIGHT_R;
|
||||
$weightF = self::DEFAULT_WEIGHT_F;
|
||||
$weightM = self::DEFAULT_WEIGHT_M;
|
||||
}
|
||||
|
||||
// 计算时间范围
|
||||
@@ -111,6 +116,8 @@ class RFMController extends BaseController
|
||||
|
||||
// 3. 异常值处理 - 剔除大额异常订单
|
||||
$mValues = array_column($customerData, 'M');
|
||||
$abnormalThreshold = null; // 初始化异常阈值
|
||||
|
||||
if (!empty($mValues)) {
|
||||
sort($mValues);
|
||||
$m99Percentile = $this->percentile($mValues, 0.99);
|
||||
@@ -120,6 +127,11 @@ class RFMController extends BaseController
|
||||
foreach ($customerData as &$customer) {
|
||||
$customer['isAbnormal'] = $customer['M'] > $abnormalThreshold;
|
||||
}
|
||||
} else {
|
||||
// 如果没有M值数据,标记所有客户为非异常
|
||||
foreach ($customerData as &$customer) {
|
||||
$customer['isAbnormal'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 使用五分位法计算各维度的区间阈值
|
||||
@@ -127,7 +139,7 @@ class RFMController extends BaseController
|
||||
$fThresholds = $this->calculatePercentiles(array_column($customerData, 'F'), false);
|
||||
// M维度排除异常值计算区间
|
||||
$mValuesForPercentile = array_filter(array_column($customerData, 'M'), function($m) use ($abnormalThreshold) {
|
||||
return isset($abnormalThreshold) ? $m <= $abnormalThreshold : true;
|
||||
return $abnormalThreshold !== null ? $m <= $abnormalThreshold : true;
|
||||
});
|
||||
$mThresholds = $this->calculatePercentiles(array_values($mValuesForPercentile), false);
|
||||
|
||||
@@ -136,7 +148,7 @@ class RFMController extends BaseController
|
||||
foreach ($customerData as $customer) {
|
||||
$rScore = $this->scoreByPercentile($customer['R'], $rThresholds, true); // R是反向的
|
||||
$fScore = $this->scoreByPercentile($customer['F'], $fThresholds, false);
|
||||
$mScore = $customer['isAbnormal'] ? 5 : $this->scoreByPercentile($customer['M'], $mThresholds, false); // 异常值给最高分
|
||||
$mScore = isset($customer['isAbnormal']) && $customer['isAbnormal'] ? 5 : $this->scoreByPercentile($customer['M'], $mThresholds, false); // 异常值给最高分
|
||||
|
||||
// 计算RFM总分(加权求和)
|
||||
$rfmScore = $rScore * $weightR + $fScore * $weightF + $mScore * $weightM;
|
||||
@@ -146,7 +158,8 @@ class RFMController extends BaseController
|
||||
if ($scoreScale == 100) {
|
||||
$rfmMin = $weightR * 1 + $weightF * 1 + $weightM * 1;
|
||||
$rfmMax = $weightR * 5 + $weightF * 5 + $weightM * 5;
|
||||
$standardScore = (int)round(($rfmScore - $rfmMin) / ($rfmMax - $rfmMin) * 99 + 1);
|
||||
$range = $rfmMax - $rfmMin;
|
||||
$standardScore = $range > 0 ? (int)round(($rfmScore - $rfmMin) / $range * 99 + 1) : 1;
|
||||
}
|
||||
|
||||
$results[] = [
|
||||
@@ -187,7 +200,7 @@ class RFMController extends BaseController
|
||||
],
|
||||
'statistics' => [
|
||||
'total_customers' => count($results),
|
||||
'avg_rfm_score' => round(array_sum(array_column($results, 'RFM_score')) / count($results), 2),
|
||||
'avg_rfm_score' => count($results) > 0 ? round(array_sum(array_column($results, 'RFM_score')) / count($results), 2) : 0,
|
||||
]
|
||||
]
|
||||
];
|
||||
@@ -352,7 +365,7 @@ class RFMController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新RFM值到 ck_traffic_source_v1 和 s2_wechat_friend 表
|
||||
* 更新RFM值到 ck_traffic_source_v1、s2_wechat_friend 和 ck_traffic_pool_company 表
|
||||
*
|
||||
* @param array $results RFM计算结果数组
|
||||
* @param string|null $ownerWechatId 微信ID,用于过滤更新范围
|
||||
@@ -365,8 +378,11 @@ class RFMController extends BaseController
|
||||
$rScore = (string)$result['R_score'];
|
||||
$fScore = (string)$result['F_score'];
|
||||
$mScore = (string)$result['M_score'];
|
||||
$rfmRaw = $result['R_raw'];
|
||||
$rfmF = $result['F_raw'];
|
||||
$rfmM = $result['M_raw'];
|
||||
|
||||
// 更新 ck_traffic_source_v1 表
|
||||
// 更新 ck_traffic_source_v1 表(V1旧表)
|
||||
// 根据 identifier 更新所有匹配的记录
|
||||
$trafficSourceUpdate = [
|
||||
'R' => $rScore,
|
||||
@@ -389,6 +405,18 @@ class RFMController extends BaseController
|
||||
$wechatFriendWhere['ownerWechatId'] = $ownerWechatId;
|
||||
}
|
||||
WechatFriendModel::where($wechatFriendWhere)->update($wechatFriendUpdate);
|
||||
|
||||
// 更新 ck_traffic_pool_company 表(V2新表)
|
||||
// 根据 identifier 更新,identifier可能是wechatId、phone等
|
||||
$poolCompanyUpdate = [
|
||||
'rfmF' => $rfmF,
|
||||
'rfmM' => $rfmM,
|
||||
'updateTime' => date('Y-m-d H:i:s')
|
||||
];
|
||||
Db::table('ck_traffic_pool_company')
|
||||
->where('identifier', $identifier)
|
||||
->where('isDel', 0)
|
||||
->update($poolCompanyUpdate);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
Reference in New Issue
Block a user