1. 目的
携帯電話ネットワークは、ユーザーのスマートフォンに関する情報を記録します。例えば、どの基地局エリアにいるかや、そのエリアに滞在している時間などです。これらのデータを使用してビジネス圏を分析し、潜在的な顧客の分布を理解することで、適切なビジネス戦略を立案することができます。例えば、商業地域、住宅地域、または業務地域に分類できます。
2. データ
以下のような形式で与えられるデータセットを使います。このデータセットは既に集計、変換、フィルタリングが行われています。
基站编号,工作日上班时间人均停留时间,凌晨人均停留时间,周末人均停留时间,日均人流量
36902,78,521,602,2863
36903,144,600,521,2245
36904,95,457,468,1283
36905,69,596,695,1054
各特徴量は次の通りです:
- 平日の勤務時間(9:00-18:00)における平均滞在時間
- 凌晨時間帯(00:00-07:00)における平均滞在時間
- 週末における平均滞在時間
- 日平均人流
3. コード
特徴量を抽出・処理し、クラスタリング手法を利用して複数の区域に分類します。それぞれの区域について分析を行います。
public static void analyzeBusinessZones(SparkSession session) {
String path = PropertiesReader.get("processed_business_zone_data");
// CSVデータの読み込み
Dataset<Row> rawDataset = session.read()
.option("sep", ",")
.option("header", "true")
.option("inferSchema", "true")
.csv(path);
// 特徴ベクトルへの変換
Dataset<Row> featureDataset = rawDataset.map((MapFunction<Row, Row>) row -> {
int stationId = row.getInt(0);
double weekdayStay = (double) row.getInt(1);
double nightStay = (double) row.getInt(2);
double weekendStay = (double) row.getInt(3);
double dailyTraffic = (double) row.getInt(4);
return RowFactory.create(stationId, Vectors.dense(new double[] {
dailyTraffic, weekendStay, nightStay, weekdayStay
}));
}, RowEncoder.apply(new StructType(new StructField[] {
new StructField("stationId", DataTypes.IntegerType, false, Metadata.empty()),
new StructField("features", SQLDataTypes.VectorType(), false, Metadata.empty())
})));
// データの正規化
MinMaxScalerModel scalerModel = new MinMaxScaler()
.setInputCol("features")
.setOutputCol("normalizedFeatures")
.fit(featureDataset);
Dataset<Row> normalizedDataset = scalerModel.transform(featureDataset);
// 最適なクラスター数の選定
int optimalK = determineOptimalClusters(normalizedDataset, 10);
// クラスタリングモデルの構築
BisectingKMeans clusteringModel = new BisectingKMeans()
.setFeaturesCol("normalizedFeatures")
.setK(optimalK)
.setSeed(42);
BisectingKMeansModel model = clusteringModel.fit(normalizedDataset);
// 結果の予測
Dataset<Row> predictions = model.transform(normalizedDataset);
// クラスター中心点の取得
Vector[] clusterCenters = model.clusterCenters();
for (Vector center : clusterCenters) {
System.out.println(center);
}
// 上位5件の結果を表示
predictions.show(5);
}
private static int determineOptimalClusters(Dataset<Row> data, int maxK) {
double bestSilhouette = -1;
int optimalK = 2;
for (int k = 2; k <= maxK; k++) {
BisectingKMeans tempModel = new BisectingKMeans()
.setK(k)
.setSeed(1);
BisectingKMeansModel tempCluster = tempModel.fit(data);
double silhouetteScore = Silhouette.silhouette(tempCluster, data);
if (silhouetteScore > bestSilhouette) {
bestSilhouette = silhouetteScore;
optimalK = k;
}
}
return optimalK;
}