ヒートマップ上の不動産のコスト

この記事では、モスクワとサンクトペテルブルクの不動産販売価格のヒートマップを作成するプロセスについて説明します。







モスクワ価格のヒートマップ







私の名前はドミトリーです。私はサンクトペテルブルクのプログラマーであり、趣味があります。これは、今から5年近くフリータイムにやっている不動産ポータルです。 このサイトは著作権で保護されており、これにより、アイデアを実験および実装するための十分なレベルの自由が与えられます。 そして、古いアイデアの1つは、熱価格マップを作成することでした。







記事を読むのが面倒な場合は、 ここで完成した結果をタッチしてください







不動産専用のサイトが豊富にあるため、RuNetには通常の価格マップはありません。 エリアが異なる色でペイントされている非常にわかりにくいマップがいくつかありますが、それだけではありません。 この地域の平均価格はそれについてほとんど語っていません。価格が一桁以上変動する地域もあります。 ヒートマップを作成するというアイデアは、長い間私を訪れてきましたが、困難を予想して、私はそれを取りたくありませんでした-十分なインスピレーションや何かがありませんでした。







いつものように、 サラトフの不動産価格の統計に関する記事を偶然見つけました。 筆者は、私がやりたかったこと、つまり想像したとおりの地図を正確に説明しています。 実際、それは私にインスピレーションを与えました。







ツール



この記事にはソースへのリンクがありますが、私はPython(またはpython)で理解できず、新しい言語を習得するという目標もありませんでした。 .Net。







画像生成の最初のコンポーネントとして、 Googleが提供するものを試しました







それは完全に間違っていることが判明しました。 ここでは、強度マップがより可能性が高い-それらはマップ上のオブジェクトの密度を視覚化するのに適していますが、価格の表示には適していません。 さらに、マップをスケーリングすると、ポイントがより激しくなります-これは絶対に価値がありません。













この方法を使用して、価格マップが実装されているベラルーシのサイトが1つあります。 こちらで見れます







価格マップresta.by







このカードを見て、どこがより高価でどこがより安いかを誰が知ることができますか? できません。 一般的に、これは... 10分の3です。







検索が続き、ついにこれをスタック上でグーグルで検索しました。その人は、私に興味のある質問、すなわち、強度マップではなくヒートマップの作成方法を正確に尋ねます。 そして答えには、必要なことを行うJSライブラリへのリンクがあります。 計算には、 逆距離重み付けが使用されます。 JSは確かにシャープではありませんが、近いので、私はとても幸せでした。 特にjsfiddleですべてを「感じた」後、結果が有効であることを確認しました。 数時間後、C#で動作するコードが既にありました(その後大幅に改善されました)。 Githubへリンクは、誰かが必要な場合です。







データ



ポータルの運用中に、ロシア全体で2,000万を超えるオブジェクトを蓄積しました(アーカイブオブジェクトは永久に保存されます)。







生データの処理方法は明らかな問題ではありません。 手始めに、フィルター:販売対象、新しい建物と二次、そしてアパートと家だけです。平方メートルあたりのコストを正確に計算できるため、メーターのコストを最も客観的な指標として地図に表示するつもりでした。 たくさんのゴミがあるので家賃は好きではありません。 価格はひどく歪んでおり、多くの架空の広告などがあります。 これもすべて販売中ですが、小規模です。 さらに、賃貸価格はアパートの販売コストに直接依存するため、最終的なマップは、凡例の値に添付されない場合でも、全体像を視覚化するのに非常に適しています。







すべての商取引、区画、駐車場を除外する必要がありましたが、これらのカテゴリのそれぞれについて、結果を見るのも面白いでしょうが、どういうわけか後で。 さらに、古いオブジェクトをそこに含めることはおそらく意味がなく、価格は変化しています。 6か月間、量は正常で価格に関連性があることが決定されました。 モスクワでは約40,000個、サンクトペテルブルクでは約30,000個のオブジェクトが見つかりました。







マップ上の開始点にオブジェクトを組み立てるための最適なステップをまだ決定できませんでした。 100メートルから5キロメートルまでさまざまなオプションを試しました。 私は、ユーザーの裁量で最も興味深い3つのオプション、250、500、および1000メートルを残すことにしました。







ポイントは次のように生成されます。セクションサイズが最小値に一致するか、最小値をわずかに超えるまで、またはエリア内のオブジェクトの最小数(たとえば3)未満になるまで、エリアは4つの長方形セクションに再帰的に分割されます。 3つ未満のオブジェクトがあるセクションの場合、最終的なポイントは作成されません。これらの孤独なオブジェクトは周囲のオブジェクトと価格が異なることが多いため、全体像をゆがめ、過度の「漏れ」を作成します。







ヒートマップポイント







結果の各セクション内で、オブジェクトの平均価格が考慮され、最終ポイントが設定されます。 座標はセクションの中心に設定されていませんが、平均値はすべてのオブジェクトの座標によって計算されます。







各ステップ(250、500、1000)に対して、独自のポイントセットが生成されます。 各ポイントについて、使用されているオブジェクトのリストは、マップをクリックして表示するために保存されます。







データベース内のポイントの座標は地理データの形式で保存されるため、それらを作業に渡す前に、座標をワールドに変換してから、最終ビットマップのピクセル座標に変換する必要があります。 世界座標とはここで読むことができます 。 一言で言えば、地理座標は球体上に配置することを意味し、平面上に表示するには特定の方法で変換する必要があります。 これは、世界座標とピクセル座標を取得するためのコードを取得した場所です。







250メートルの値の最小グリッド間隔を考えると、マップのズームを8から14に制限することにしました。これは、近くを検討する意味がありません。







タイル



最初は、1つの大きなビットマップを作成し、それを小さなフラグメントに分割する方が良いと考えました。 しかし、最終的に、私は反対のことをしました-小さな断片が生成されます-タイル(タイル)、その後、それらはそれぞれのズームのために配置されます。







次に、すべてをマップに表示するには、それらを対応する座標にバインドする必要があります。 私が検索で最初に見つけたのは、 Ground Overlaysでした。







数時間の作業の後、私は視覚的な結果をかなり得ましたが、1つの問題がありました。マップをナビゲートするときのひどいブレーキです。 明らかに、多数のフラグメントを操作することは、このメカニズムの目的ではありません。







彼はさらにグーグルで検索を開始し、 Tile Overlaysを見つけました。結局、必要なものが判明しました。 一番下の行は次のとおりです。各マップのズームレベルごとに、最終画像は256 x 256ピクセルのタイルで構成されます。タイルごとに独自の画像をオーバーレイできます。 マップをナビゲートすると、表示領域に収まり、ズームインデックスの値に対応するタイルのみがロードされます。







地域の境界



私は常に地域の境界の座標を持っていたので、これにより作業が少し簡単になりました。 各タイルを生成する際に、タイルをトリミングする必要があるかどうかをチェックし、必要に応じてトリミングして、非落下領域を透明にします。







その結果を見て、ユーザーは公式の境界線にあまり興味がなく、おそらく近くのエリアも見る方が便利だと思いました。 都市(モスクワとサンクトペテルブルク)と最も近いエリアの両方を直接キャプチャするマップの境界線を描画する必要がありました。 オブジェクトの数は数回増加しています。 現在、モスクワとサンクトペテルブルクにはそれぞれ約14万と5万があります。







モスクワ:







モスクワ地区







サンクトペテルブルク:







SPBエリア







境界線を描画して座標を取得するために、codepen.ioの誰かが用意したコードを少し変更して使用しました。 これがモスクワサンクトペテルブルクのリンクです。 マップ上のポイントのいずれかを変更した後、地理座標のリストがデータベースへの挿入に便利な形式で下のウィンドウに挿入されます。







後にこの問題が発見されました。異なる価格カテゴリのエリアが非常に近くにあるため、1つのセグメントに分類され、平均価格が考慮される場合があります。 たとえば、サンクトペテルブルクにはエリート不動産のみが販売されているカメニー島とクレストフスキー島があり、幅300メートルの川を渡るとフルシチョフのある普通の地区があります。 価格の差は1桁以上です(1200 trに対して98 tr)。







カメニー島







図ではカメニー島であり、赤い点は、1000メートルのステップで最終セクションに落ちるその両側のオブジェクトを示します。 これは、ポジションの平均価格に大きく影響し、全体像をゆがめます。







解決策は次のとおりです。一部のセクションを選択し、オブジェクトを配置する際に、そのセクションに入ったオブジェクトを、欠落していないオブジェクトや別のセクションに入ったオブジェクトと混合しないでください。 ピーターの島も選択しました。







SPB分離エリア







ここでは精度は重要ではありません。 主なことは、地域間に交差点がないことです。







色の選択



色を選択したり、レベル数を調整したりできるように、ヒートマップを生成するプロセスをカスタマイズ可能にしました。

たとえば、-100〜100の値で設定された6ポイントで500 x 500ピクセルの領域の場合、このようなオプションを取得できます。







値を持つテストポイント:







テストポイント







レベルのあるマップ上の同じデータ:







MapWithTestPoints







色の制限なしおよびレベル別:













色の制限があり、レベルがない場合:













手動で定義された色:













長くて苦しい実験の後、デフォルトのセットとしてクラスにハードコードされた独自の色のセット( ここで借用)が優先されました。







500メートルのステップでの結果は次のようになります。







500mマップ







性能



6並列スレッド(3.2 GHzの8コアサーバー)を備えたモスクワ専用のカードを生成するのに1日以上かかりました。 将来的にはより多くの地域が存在し、少なくとも週に1回はスケジュールどおりに起動する必要があるため、これはまったく受け入れられません。







アルゴリズムのボトルネックは、タイルの各ピクセルの色の計算です。 このピクセルからの距離ですべてのポイントをソートする必要があります。 つまり、6000ポイントの配列を256x256回並べ替える必要がありました。 リソースの無駄。 明らかに、すべてのポイントが必要というわけではなく、最も近いポイントに制限することができます。 最も簡単な解決策は、たとえば、タイルの中心からの距離でソートされた上位100ポイントを取得することです。 ただし、たとえば、片側からのみ、次の100ポイントがグループ内にある場合があります。 すなわち 最も近い100だけでなく、周囲にも配置する必要があります。 これが私がしたことです:タイルの中央から全方向に10度のステップで、光線はマップ全体の長さの3分の1ずつに分配されます。 各光線は、少なくとも5つのポイントが存在するか、長さが制限に達するまで成長します。 したがって、最終リストで保証されるのは、すべての側から約150ポイントです。







このように見えます(緑の点-サンプルに落ち、赤-その他すべて。中央の赤い四角はタイル自体です):







自転車







美しく、面白くてねばねばしていますが、まったく役に立ちません。 自転車、その古典的な症状。 レイの数、その長さ、各レイのポイント数などのパラメーターを実験するために丸1日過ごしました。 そして、常にマップ上でエラーが発生しました。







次のようになります。













これらは常に境界が丸くなければならない領域の角度です。 これらのエラーは、データの集中度が低い場所で常に発生します。







その結果、このメカニズム全体を廃棄する必要がありました。 最も単純で最も明白な方法が最適です-タイル自体にあるものを考慮せずに100の最も近いポイント。 エラーはマップ上に残りましたが、ほとんど何も販売されていないので、それらは人々にとってほとんど興味のない場所にあります。







作業速度が大幅に向上しました。 モスクワまで約3時間かかりますが、そのうち約1時間はデータ処理のみで、残りは直接描画に使用されます。







オブジェクトを表示



マップをクリックすると、クリックした場所に最も近いポイントが選択され、そのための要約情報が表示されます:メーターあたりの平均価格と計算に使用されるオブジェクトのリスト。 また、マップ上の赤い点は、これらのオブジェクトの座標を表示します。 リンクをクリックすると、各カードにアクセスして詳細を確認できます。 多くのオブジェクトはアーカイブされているため、販売者の写真と連絡先は表示されない場合がありますが、そうでない場合、すべての情報は元の情報に対応します。







表示ポイント







おわりに



近い将来、データベース上のオブジェクトのほとんどには地理座標がないため、マップ上のオブジェクトの数を増やす予定です。 これを行うには、そのようなオブジェクトを毎日通過し、GoogleまたはYandexサービスを介して住所でそれらの座標を受け取るジオロケーションモジュールを作成する必要があります。







また、表形式のデータ形式の統計情報を地図に追加する予定です。 価格カテゴリ、平均価格などによる内訳







参照資料



念のため、ここでリンクを記事で示されているのと同じ順序で複製します。







投稿からのリンク

https://habrahabr.ru/post/324596/

https://developers.google.com/maps/documentation/javascript/examples/layer-heatmap

https://resta.by/karta-cen

https://stackoverflow.com/questions/30073977/create-custom-temperature-map-with-front-end-javascript

https://github.com/optimisme/javascript-temperatureMap

https://en.wikipedia.org/wiki/Inverse_distance_weighting

https://jsfiddle.net/mertk/y9gcuf65/

https://github.com/d-sky/HeatMap

https://developers.google.com/maps/documentation/javascript/maptypes?hl=en#MapCoordinates

https://developers.google.com/maps/documentation/javascript/examples/map-coordinates

https://developers.google.com/maps/documentation/javascript/examples/groundoverlay-simple

https://developers.google.com/maps/documentation/android-api/tileoverlay

https://codepen.io/d-sky/pen/JJqpYe

https://codepen.io/d-sky/pen/PKJzoO

https://www.ventusky.com/?p=9;71;1&l=temperature

https://kvartiri-domiki.ru/karta-cen







PS



今、マップをナビゲートすると、約10〜15秒に1回、わずかにフリーズします。これは私のサイトのバグではなく、これが新しいMetrics Webvisorの動作です。 私はすでにYandexに手紙を書いた-彼らはそれを理解するのに時間が必要だと言った。 だから、すぐに、私はそれを修正したいと考えています。








All Articles