مقدمه
این سند نحوه ایجاد راه حل انتخاب سایت را با ترکیب مجموعه داده Places Insights ، داده های عمومی مکانی در BigQuery و Place Details API توضیح می دهد.
این بر اساس نسخه نمایشی ارائه شده در Google Cloud Next 2025 است که برای تماشا در YouTube در دسترس است.
چالش کسب و کار
تصور کنید که صاحب یک کافی شاپ زنجیره ای موفق هستید و می خواهید در ایالت جدیدی مانند نوادا گسترش پیدا کنید، جایی که هیچ حضوری ندارید. باز کردن یک مکان جدید یک سرمایه گذاری قابل توجه است و تصمیم گیری مبتنی بر داده برای موفقیت بسیار مهم است. اصلا از کجا شروع می کنی؟
این راهنما شما را از طریق تجزیه و تحلیل چند لایه راهنمایی می کند تا مکان بهینه برای یک کافی شاپ جدید را مشخص کنید. ما با یک نمای کل ایالت شروع می کنیم، به تدریج جستجوی خود را به یک شهرستان و منطقه تجاری خاص محدود می کنیم، و در نهایت یک تجزیه و تحلیل بیش از حد محلی برای امتیاز دادن به مناطق جداگانه و شناسایی شکاف های بازار با ترسیم رقبا انجام می دهیم.
گردش کار راه حل
این فرآیند از یک قیف منطقی پیروی میکند، شروع میشود و به تدریج دانهبندیتر میشود تا ناحیه جستجو را اصلاح کرده و اطمینان را در انتخاب سایت نهایی افزایش دهد.
پیش نیازها و تنظیمات محیطی
قبل از فرو رفتن در تحلیل، به محیطی با چند قابلیت کلیدی نیاز دارید. در حالی که این راهنما پیاده سازی را با استفاده از SQL و Python انجام می دهد، اصول کلی را می توان در سایر پشته های فناوری اعمال کرد.
به عنوان یک پیش نیاز، اطمینان حاصل کنید که محیط شما می تواند:
- کوئری ها را در BigQuery اجرا کنید.
- برای اطلاعات بیشتر به Insights Places دسترسی پیدا کنید، به Setup Places Insights مراجعه کنید
- اشتراک در مجموعه دادههای عمومی از
bigquery-public-data
و مجموع جمعیت شهرستان اداره سرشماری ایالات متحده
شما همچنین باید بتوانید داده های مکانی را روی نقشه تجسم کنید ، که برای تفسیر نتایج هر مرحله تحلیلی بسیار مهم است. راه های زیادی برای رسیدن به این هدف وجود دارد. میتوانید از ابزارهای BI مانند Looker Studio که مستقیماً به BigQuery متصل میشوند، یا میتوانید از زبانهای علم داده مانند Python استفاده کنید.
تجزیه و تحلیل در سطح ایالت: بهترین شهرستان را پیدا کنید
اولین قدم ما یک تجزیه و تحلیل گسترده برای شناسایی امیدوار کننده ترین شهرستان در نوادا است. امیدوارکننده را ترکیبی از جمعیت زیاد و تراکم زیاد رستورانهای موجود تعریف میکنیم که نشاندهنده فرهنگ قوی غذا و نوشیدنی است.
پرس و جو BigQuery ما این کار را با استفاده از اجزای آدرس داخلی موجود در مجموعه داده Places Insights انجام می دهد. پرس و جو رستوران ها را با استفاده از فیلد administrative_area_level_1_name
، ابتدا فیلتر می کند تا داده ها را فقط در ایالت نوادا شامل شود. سپس این مجموعه را بیشتر اصلاح میکند تا فقط مکانهایی را شامل شود که آرایه انواع حاوی " restaurant
" است. در نهایت، این نتایج را بر اساس نام شهرستان ( administrative_area_level_2_name
) گروه بندی می کند تا یک تعداد برای هر شهرستان تولید کند. این رویکرد از ساختار آدرس داخلی و از پیش نمایهشده مجموعه داده استفاده میکند.
این گزیده نشان میدهد که چگونه به هندسههای شهرستانها با Places Insights ملحق میشویم و برای یک نوع مکان خاص، restaurant
فیلتر میکنیم:
SELECT WITH AGGREGATION_THRESHOLD
administrative_area_level_2_name,
COUNT(*) AS restaurant_count
FROM
`places_insights___us.places`
WHERE
-- Filter for the state of Nevada
administrative_area_level_1_name = 'Nevada'
-- Filter for places that are restaurants
AND 'restaurant' IN UNNEST(types)
-- Filter for operational places only
AND business_status = 'OPERATIONAL'
-- Exclude rows where the county name is null
AND administrative_area_level_2_name IS NOT NULL
GROUP BY
administrative_area_level_2_name
ORDER BY
restaurant_count DESC
تعداد خام رستوران ها کافی نیست. ما باید آن را با داده های جمعیت متعادل کنیم تا حس واقعی اشباع بازار و فرصت را به دست آوریم. ما از داده های جمعیت از مجموع جمعیت شهرستان اداره سرشماری ایالات متحده استفاده خواهیم کرد.
برای مقایسه این دو معیار بسیار متفاوت (تعداد مکان در مقابل تعداد جمعیت زیاد)، از نرمال سازی حداقل حداکثر استفاده می کنیم. این تکنیک هر دو معیار را در یک محدوده مشترک (0 تا 1) مقیاس می کند. سپس آنها را در یک normalized_score
واحد ترکیب می کنیم و به هر متریک 50 درصد وزن برای مقایسه متعادل می دهیم.
این گزیده منطق اصلی برای محاسبه امتیاز را نشان می دهد. این تعداد جمعیت عادی و رستوران ها را ترکیب می کند:
(
-- Normalize restaurant count (scales to a 0-1 value) and apply 50% weight
SAFE_DIVIDE(restaurant_count - min_restaurants, max_restaurants - min_restaurants) * 0.5
+
-- Normalize population (scales to a 0-1 value) and apply 50% weight
SAFE_DIVIDE(population_2023 - min_pop, max_pop - min_pop) * 0.5
) AS normalized_score
پس از اجرای پرس و جوی کامل، لیستی از شهرستان ها، تعداد رستوران ها، جمعیت و امتیاز عادی برگردانده می شود. مرتب سازی بر اساس normalized_score DESC
نشان می دهد که Clark County به عنوان برنده واضح برای تحقیقات بیشتر به عنوان مدعی برتر است.
این اسکرین شات 4 شهرستان برتر را با امتیاز عادی نشان می دهد. شمارش جمعیت خام به طور هدفمند از این مثال حذف شده است.
تجزیه و تحلیل سطح شهرستان: شلوغ ترین مناطق تجاری را پیدا کنید
اکنون که شهرستان کلارک را شناسایی کردهایم، قدم بعدی بزرگنمایی برای یافتن کدهای پستی با بیشترین فعالیت تجاری است. بر اساس دادههای کافیشاپهای موجود ما، میدانیم که عملکرد زمانی بهتر است که در نزدیکی تراکم بالای مارکهای اصلی قرار بگیرند، بنابراین از آن به عنوان یک پروکسی برای ترافیک زیاد استفاده میکنیم.
این جستجو از جدول brands
در Places Insights استفاده میکند که حاوی اطلاعاتی درباره مارکهای خاص است. این جدول را می توان برای کشف لیست مارک های پشتیبانی شده جستجو کرد . ابتدا فهرستی از مارکهای هدف خود را تعریف میکنیم و سپس به مجموعه دادههای Places Insights اصلی میپیوندیم تا شمارش کنیم که چه تعداد از این فروشگاههای خاص در هر کد پستی در شهرستان کلارک قرار دارند.
کارآمدترین راه برای دستیابی به این هدف، رویکرد دو مرحله ای است:
- ابتدا، یک تجمیع سریع و غیرمکانی برای شمارش مارکهای موجود در هر کد پستی انجام میدهیم.
- دوم، ما آن نتایج را به یک مجموعه داده عمومی میپیوندیم تا مرزهای نقشه را برای تجسم به دست آوریم.
شمارش برندها با استفاده از قسمت postal_code_names
این اولین کوئری منطق شمارش هسته را انجام می دهد. مکانها را در شهرستان کلارک فیلتر میکند و سپس آرایه postal_code_names را جدا میکند تا تعداد برندها را بر اساس کد پستی گروهبندی کند.
WITH brand_names AS (
-- First, select the chains we are interested in by name
SELECT
id,
name
FROM
`places_insights___us.brands`
WHERE
name IN ('7-Eleven', 'CVS', 'Walgreens', 'Subway Restaurants', "McDonald's")
)
SELECT WITH AGGREGATION_THRESHOLD
postal_code,
COUNT(*) AS total_brand_count
FROM
`places_insights___us.places` AS places_table,
-- Unnest the built-in postal code and brand ID arrays
UNNEST(places_table.postal_code_names) AS postal_code,
UNNEST(places_table.brand_ids) AS brand_id
JOIN
brand_names
ON brand_names.id = brand_id
WHERE
-- Filter directly on the administrative area fields in the places table
places_table.administrative_area_level_2_name = 'Clark County'
AND places_table.administrative_area_level_1_name = 'Nevada'
GROUP BY
postal_code
ORDER BY
total_brand_count DESC
خروجی جدولی از کدهای پستی و تعداد نام تجاری مربوط به آنها است.
هندسه کد پستی را برای نگاشت پیوست کنید
اکنون که شمارش ها را داریم، می توانیم اشکال چند ضلعی مورد نیاز برای تجسم را بدست آوریم. این پرس و جوی دوم اولین پرس و جو ما را می گیرد، آن را در یک عبارت جدول مشترک (CTE) به نام brand_counts_by_zip
می پیچد و نتایج آن را به geo_us_boundaries.zip_codes table
می پیوندد. این به طور موثر هندسه را به شمارش های از پیش محاسبه شده ما متصل می کند.
WITH brand_counts_by_zip AS (
-- This will be the entire query from the previous step, without the final ORDER BY (excluded for brevity).
. . .
)
-- Now, join the aggregated results to the boundaries table
SELECT
counts.postal_code,
counts.total_brand_count,
-- Simplify the geometry for faster rendering in maps
ST_SIMPLIFY(zip_boundaries.zip_code_geom, 100) AS geography
FROM
brand_counts_by_zip AS counts
JOIN
`bigquery-public-data.geo_us_boundaries.zip_codes` AS zip_boundaries
ON counts.postal_code = zip_boundaries.zip_code
ORDER BY
counts.total_brand_count DESC
خروجی جدولی از کدهای پستی، تعداد نام تجاری مربوطه آنها و هندسه کد پستی است.
ما می توانیم این داده ها را به عنوان یک نقشه حرارتی تجسم کنیم . نواحی قرمز تیره تر نشان دهنده غلظت بالاتر برندهای هدف ما است و ما را به سمت متراکم ترین مناطق تجاری در لاس وگاس سوق می دهد.
تجزیه و تحلیل بیش از حد محلی: امتیاز مناطق شبکه ای فردی
پس از شناسایی منطقه کلی لاس وگاس، زمان آن رسیده است که یک تجزیه و تحلیل دقیق انجام دهیم. این جایی است که ما در دانش تجاری خاص خود لایه لایه می کنیم. ما می دانیم که یک کافی شاپ عالی در نزدیکی سایر مشاغلی که در ساعات شلوغ ما شلوغ هستند، مانند ویترین اواخر صبح و ناهار، رونق می گیرد.
پرس و جو بعدی ما واقعاً خاص می شود. با ایجاد یک شبکه شش ضلعی ریز دانه بر روی منطقه شهری لاس وگاس با استفاده از شاخص جغرافیایی استاندارد H3 (در وضوح 8) برای تجزیه و تحلیل منطقه در سطح میکرو شروع می شود. پرس و جو ابتدا همه مشاغل تکمیلی را که در اوج پنجره باز هستند (دوشنبه، 10 صبح تا 2 بعد از ظهر) شناسایی می کند.
سپس برای هر نوع مکان یک امتیاز وزنی اعمال می کنیم. یک رستوران نزدیک برای ما از یک فروشگاه رفاهی با ارزش تر است، بنابراین ضریب بالاتری دریافت می کند. این به ما یک suitability_score
سفارشی برای هر منطقه کوچک می دهد.
این گزیده منطق امتیازدهی وزنی را برجسته میکند، که به یک پرچم از پیش محاسبهشده ( is_open_monday_window
) برای بررسی ساعات کار اشاره میکند:
. . .
(
COUNTIF('restaurant' IN UNNEST(types) AND is_open_monday_window) * 8 +
COUNTIF('convenience_store' IN UNNEST(types) AND is_open_monday_window) * 3 +
COUNTIF('bar' IN UNNEST(types) AND is_open_monday_window) * 7 +
COUNTIF('tourist_attraction' IN UNNEST(types) AND is_open_monday_window) * 6 +
COUNTIF('casino' IN UNNEST(types) AND is_open_monday_window) * 7
) AS suitability_score
. . .
برای پرس و جو کامل باز کنید
-- This query calculates a custom 'suitability score' for different areas in the Las Vegas -- metropolitan area to identify prime commercial zones. It uses a weighted model based -- on the density of specific business types that are open during a target time window. -- Step 1: Pre-filter the dataset to only include relevant places. -- This CTE finds all places in our target localities (Las Vegas, Spring Valley, etc.) and -- adds a boolean flag 'is_open_monday_window' for those open during the target time. WITH PlacesInTargetAreaWithOpenFlag AS ( SELECT point, types, EXISTS( SELECT 1 FROM UNNEST(regular_opening_hours.monday) AS monday_hours WHERE monday_hours.start_time <= TIME '10:00:00' AND monday_hours.end_time >= TIME '14:00:00' ) AS is_open_monday_window FROM `places_insights___us.places` WHERE EXISTS ( SELECT 1 FROM UNNEST(locality_names) AS locality WHERE locality IN ('Las Vegas', 'Spring Valley', 'Paradise', 'North Las Vegas', 'Winchester') ) AND administrative_area_level_1_name = 'Nevada' ), -- Step 2: Aggregate the filtered places into H3 cells and calculate the suitability score. -- Each place's location is converted to an H3 index (at resolution 8). The query then -- calculates a weighted 'suitability_score' and individual counts for each business type -- within that cell. TileScores AS ( SELECT WITH AGGREGATION_THRESHOLD -- Convert each place's geographic point into an H3 cell index. `carto-os.carto.H3_FROMGEOGPOINT`(point, 8) AS h3_index, -- Calculate the weighted score based on the count of places of each type -- that are open during the target window. ( COUNTIF('restaurant' IN UNNEST(types) AND is_open_monday_window) * 8 + COUNTIF('convenience_store' IN UNNEST(types) AND is_open_monday_window) * 3 + COUNTIF('bar' IN UNNEST(types) AND is_open_monday_window) * 7 + COUNTIF('tourist_attraction' IN UNNEST(types) AND is_open_monday_window) * 6 + COUNTIF('casino' IN UNNEST(types) AND is_open_monday_window) * 7 ) AS suitability_score, -- Also return the individual counts for each category for detailed analysis. COUNTIF('restaurant' IN UNNEST(types) AND is_open_monday_window) AS restaurant_count, COUNTIF('convenience_store' IN UNNEST(types) AND is_open_monday_window) AS convenience_store_count, COUNTIF('bar' IN UNNEST(types) AND is_open_monday_window) AS bar_count, COUNTIF('tourist_attraction' IN UNNEST(types) AND is_open_monday_window) AS tourist_attraction_count, COUNTIF('casino' IN UNNEST(types) AND is_open_monday_window) AS casino_count FROM -- CHANGED: This now references the CTE with the expanded area. PlacesInTargetAreaWithOpenFlag -- Group by the H3 index to ensure all calculations are per-cell. GROUP BY h3_index ), -- Step 3: Find the maximum suitability score across all cells. -- This value is used in the next step to normalize the scores to a consistent scale (e.g., 0-10). MaxScore AS ( SELECT MAX(suitability_score) AS max_score FROM TileScores ) -- Step 4: Assemble the final results. -- This joins the scored tiles with the max score, calculates the normalized score, -- generates the H3 cell's polygon geometry for mapping, and orders the results. SELECT ts.h3_index, -- Generate the hexagonal polygon for the H3 cell for visualization. `carto-os.carto.H3_BOUNDARY`(ts.h3_index) AS h3_geography, ts.restaurant_count, ts.convenience_store_count, ts.bar_count, ts.tourist_attraction_count, ts.casino_count, ts.suitability_score, -- Normalize the score to a 0-10 scale for easier interpretation. ROUND( CASE WHEN ms.max_score = 0 THEN 0 ELSE (ts.suitability_score / ms.max_score) * 10 END, 2 ) AS normalized_suitability_score FROM -- A cross join is efficient here as MaxScore contains only one row. TileScores ts, MaxScore ms -- Display the highest-scoring locations first. ORDER BY normalized_suitability_score DESC;
تجسم این امتیازات روی نقشه مکان های برنده واضح را نشان می دهد. تیره ترین کاشی های بنفش، عمدتاً در نزدیکی نوار لاس وگاس و مرکز شهر، مناطقی هستند که بیشترین پتانسیل را برای کافی شاپ جدید ما دارند.
تجزیه و تحلیل رقبا: کافی شاپ های موجود را شناسایی کنید
مدل مناسب ما با موفقیت مناطق امیدوار کننده را شناسایی کرده است، اما نمره بالا به تنهایی موفقیت را تضمین نمی کند. اکنون باید این را با دادههای رقیب همپوشانی کنیم. مکان ایده آل یک منطقه با پتانسیل بالا با تراکم کم کافی شاپ های موجود است، زیرا ما به دنبال شکاف بازار واضح هستیم.
برای رسیدن به این هدف، از تابع PLACES_COUNT_PER_H3
استفاده می کنیم. این تابع برای برگرداندن موثر شمارش مکان ها در یک جغرافیای مشخص، توسط سلول H3 طراحی شده است.
ابتدا، ما به صورت پویا جغرافیا را برای کل منطقه متروی لاس وگاس تعریف می کنیم. به جای تکیه بر یک محل واحد، از مجموعه داده های عمومی Overture Maps پرس و جو می کنیم تا مرزهای لاس وگاس و مناطق کلیدی اطراف آن را بدست آوریم و آنها را در یک چند ضلعی با ST_UNION_AGG
ادغام کنیم. سپس این ناحیه را به تابع منتقل می کنیم و از آن می خواهیم که تمام کافی شاپ های عملیاتی را شمارش کند.
این پرس و جو منطقه مترو را تعریف می کند و تابع را برای دریافت تعداد کافی شاپ در سلول های H3 فراخوانی می کند:
-- Define a variable to hold the combined geography for the Las Vegas metro area.
DECLARE las_vegas_metro_area GEOGRAPHY;
-- Set the variable by fetching the shapes for the five localities from Overture Maps
-- and merging them into a single polygon using ST_UNION_AGG.
SET las_vegas_metro_area = (
SELECT
ST_UNION_AGG(geometry)
FROM
`bigquery-public-data.overture_maps.division_area`
WHERE
country = 'US'
AND region = 'US-NV'
AND names.primary IN ('Las Vegas', 'Spring Valley', 'Paradise', 'North Las Vegas', 'Winchester')
);
-- Call the PLACES_COUNT_PER_H3 function with our defined area and parameters.
SELECT
*
FROM
`places_insights___us.PLACES_COUNT_PER_H3`(
JSON_OBJECT(
-- Use the metro area geography we just created.
'geography', las_vegas_metro_area,
-- Specify 'coffee_shop' as the place type to count.
'types', ["coffee_shop"],
-- Best practice: Only count places that are currently operational.
'business_status', ['OPERATIONAL'],
-- Set the H3 grid resolution to 8.
'h3_resolution', 8
)
);
این تابع جدولی را برمیگرداند که شامل شاخص سلول H3، هندسه آن، تعداد کل کافیشاپها و نمونهای از شناسههای مکان آنها است:
در حالی که تعداد کل مفید است، دیدن رقبای واقعی ضروری است. اینجا جایی است که از مجموعه داده Places Insights به Places API منتقل میشویم. با استخراج sample_place_ids
از سلولهایی با بالاترین امتیاز تناسب عادی شده، میتوانیم Place Details API را فراخوانی کنیم تا جزئیات غنی برای هر رقیب، مانند نام، آدرس، رتبهبندی و مکان آنها را بازیابی کنیم.
این امر مستلزم مقایسه نتایج جستجوی قبلی، جایی که امتیاز تناسب ایجاد شده است، و پرس و جو PLACES_COUNT_PER_H3
است. از شاخص سلولی H3 می توان برای دریافت تعداد و شناسه های کافی شاپ از سلول هایی با بالاترین امتیاز مناسب بودن نرمال استفاده کرد.
این کد پایتون نشان می دهد که چگونه می توان این مقایسه را انجام داد.
# Isolate the Top 5 Most Suitable H3 Cells
top_suitability_cells = gdf_suitability.head(5)
# Extract the 'h3_index' values from these top 5 cells into a list.
top_h3_indexes = top_suitability_cells['h3_index'].tolist()
print(f"The top 5 H3 indexes are: {top_h3_indexes}")
# Now, we find the rows in our DataFrame where the
# 'h3_cell_index' matches one of the indexes from our top 5 list.
coffee_counts_in_top_zones = gdf_coffee_shops[
gdf_coffee_shops['h3_cell_index'].isin(top_h3_indexes)
]
اکنون فهرستی از شناسههای مکان برای کافیشاپهایی داریم که از قبل در سلولهای H3 با بالاترین امتیاز مناسب وجود دارد، جزئیات بیشتری درباره هر مکان میتوان درخواست کرد.
این را می توان با ارسال مستقیم درخواست به API جزئیات مکان برای هر شناسه مکان یا استفاده از کتابخانه مشتری برای انجام تماس انجام داد. به یاد داشته باشید که پارامتر FieldMask
طوری تنظیم کنید که فقط داده های مورد نیاز خود را درخواست کند.
در نهایت، ما همه چیز را در یک تجسم واحد و قدرتمند ترکیب می کنیم. نقشه choropleth مناسب بودن بنفش خود را به عنوان لایه پایه رسم می کنیم و سپس برای هر کافی شاپ جداگانه بازیابی شده از Places API پین ها را اضافه می کنیم. این نقشه نهایی یک نمای یک نگاه ارائه می دهد که کل تحلیل ما را ترکیب می کند: مناطق بنفش تیره پتانسیل را نشان می دهد و پین های سبز واقعیت بازار فعلی را نشان می دهد.
با جستجوی سلولهای بنفش تیره با تعداد کمی پین یا بدون پین، میتوانیم با اطمینان مناطق دقیقی را که بهترین فرصت را برای مکان جدید ما نشان میدهند، مشخص کنیم.
دو سلول فوق امتیاز مناسبی بالایی دارند، اما برخی از شکاف های واضح می توانند مکان های بالقوه ای برای کافی شاپ جدید ما باشند.
نتیجه گیری
در این سند، ما از یک سوال سراسری حرکت کردیم که کجا را گسترش دهیم؟ به یک پاسخ محلی مبتنی بر داده ها. با لایه بندی مجموعه داده های مختلف و اعمال منطق تجاری سفارشی، می توانید به طور سیستماتیک ریسک مرتبط با یک تصمیم تجاری بزرگ را کاهش دهید. این گردش کار، ترکیبی از مقیاس BigQuery، غنای Places Insights، و جزئیات بیدرنگ Places API، یک الگوی قدرتمند برای هر سازمانی که به دنبال استفاده از هوش مکانی برای رشد استراتژیک است، ارائه میکند.
مراحل بعدی
- این گردش کار را با منطق کسب و کار خود، جغرافیای هدف و مجموعه داده های اختصاصی خود تطبیق دهید.
- سایر فیلدهای داده را در مجموعه داده Places Insights، مانند تعداد بازبینی، سطح قیمت و رتبهبندی کاربران، کاوش کنید تا مدل خود را غنیتر کنید.
- این فرآیند را خودکار کنید تا یک داشبورد انتخاب سایت داخلی ایجاد کنید که می تواند برای ارزیابی پویا بازارهای جدید استفاده شود.
در مستندات بیشتر غوطه ور شوید:
مشارکت کنندگان
Henrik Valve | مهندس DevX