Каждый бизнес желает знать, где сидит
фазанцелевая аудитория
Всем привет! Геоаналитика преследует меня вот уже 3 года, скоро пойдет 4-й. Начиналось все в компании Тандер (Магнит), где я в роли одного из Дата Сайнтистов проекта прогнозировала потенциальный оборот магазинов, а продолжается в Билайне, где я теперь уже занимаюсь предиктивом не только для ритейла, но и для других форматов. Помимо этого, мне удалось применить геоаналитику для анализа инвестиционной привлекательности коммерческой недвижимости, а также поработать с микробизнесом и предпринимателями, которые не обладают миллионными бюджетами для геомаркетинговых исследований, но в то же время, не очень хотят терять миллионы после выбора неудачного места открытия. Присаживайтесь поудобнее, надеюсь, будет полезно и интересно (а именно: предпринимателям, малому бизнесу, где важен правильный выбор локации и аналитикам того самого бизнеса)
В этой статье рассмотрим кейс "Как выбрать помещение для открытия кофейни?". В целом, данный подход масштабируется на любые виды бизнеса, где важна локация и то, что на ней происходит/находится.
Содержание:
Введение в геоаналитику и геомаркетинг
Работа с гексагонами: познакомимся с гексагонами (Uber H3), научимся их выгружать, визуализировать
Выгрузка, визуализация и анализ гео данных из OSM
-
Где открыть кофейню?
Бибилиотеки: geopandas, json, shapely, folium, osmnx, h3
Волшебство: пересечение (пространственный join) полигонов и точек, визуализация гео данных (нанесение точек/полигонов на карту osm и ее различное форматирование), поиск ближайших объектов и др.
Введение в геоаналитику и геомаркетинг
Геома́ркетинг (географический маркетинг) — маркетинговая дисциплина, направленная на взаимодействие с локальной аудиторией, выделенной по географическому признаку, с целью планирования, продвижения и осуществления деятельности в области сбыта продукции (wikipedia)
Проще говоря, геоаналитика - это набор инструментов и методов по работе с пространственными данными, т. е. гео (координаты, геометрии (полигоны, линии и пр.)) + аналитика (обработка, визуализация, выводы), а геомаркетинг - это дисциплина, направленная на исследование локации на предмет состава проживающей/работающей/проходящей аудитории для открытия бизнеса/проведения маркетинговых кампаний
Области применения:
розничная торговля продуктами питания (FMCG)
здравоохранение (аптеки, частные клиники)
общепит (кафе, рестораны, бары)
банковский сектор и страхование
бьюти - индустрия (салоны красоты, магазины парфюмерии и косметики)
DIY (строительные магазины)
девелопмент торговых центров и др.
Типовые задачи:
выбор оптимального размещения нового объекта
оценка потенциального объема продаж, определение класса (масс-маркет, бизнес, люкс) и состава реализуемой продукции/услуг
определение эффективного пути использования имеющегося объекта
выбор оптимальной локации для размещения наружной рекламы и др. маркетинговых оффлайн активностей
4 принципа масштабирования сети:
1) Перехват трафика
Этот принцип подразумевает открытие сетевых точек в зонах с высоким пешеходным трафиком (важно: высокий пешеходный трафик не всегда равен большому количеству целевой аудитории (ЦА) => анализируем состав ЦА), а также вблизи уже открытых точек конкурентов (важно: конкурентное преимущество)
2) Синергия
Эффект синергии достигается благодаря открытию смежных ниш бизнеса. Например: рядом с детскими товарами открывается магазин с товарами для дома/мам и пр.
3) Доступность
Принцип наименьших усилий (подробнее) - это принцип, который основан на том, что человек по природе своей стремится приложить как можно меньше усилий для получения желаемого. При наличии различных возможностей – клиент пойдёт туда, где ближе/привычнее/комфортнее. Критерии: радиус охвата, пешеходная доступность, транспортная доступность
4) Кластеризация
Торговые точки должны быть кластеризованы (распределены на группы) как минимум по следующим категориям: бюджет района, тип населенного пункта (большой/малый, поселки и пр.), формат торговой точки. Это означает, что для каждой группы необходима индивидуальная стратегия масштабирования, ценообразования, ассортиментной политики и т.д.
Его величество, BIG DATA
Развитие технологий получения, обработки и хранения геоданных позволяют творить потрясающие вещи в рамках геомаркетинговых исследований.
Используя различные приложения вы делитесь своей геопозицией
Совершая звонки, смс, используя интернет, вы автоматом попадаете в базы данных телеком операторов, поисковых порталов, а также web-сервисов
Подключаясь к WIFI в кафе, ТЦ, вы тоже попадаете в чью-то базу
И это еще не весь список, но важно отметить, что в любом геомаркетинговом исследовании эти данные обезличены и выглядят примерно так: "в радиусе 500 м проживает 666 женщин и 999 мужчин"
Какую информацию может содержать геомаркетинговое исследование локации?
Трафик (автомобильный, пешеходный):
Активность (кол-во пешеходов, кол-во автомобилей, кол-во проживающих/работающих)
Социально - демографический профиль: пол, возраст, доходы
Экономическая активность: количество чеков по категориям покупок, средний чек (ОФД)
Интересы (основаны на поисковых запросах, часто посещаемых приложениях и пр.) и др.
Геоданные:
Количество магазинов, школ, остановок, офисов, ТЦ, пешеходных переходов, парков, достопримечательностей, в общем - все, что вы можете найти на карте
На сегодняшний день, услуги по геоаналитике, геомеркетингу, внутренним ГИС - системам предоставляют компании - владельцы таких данных, а также подрядчики, которые эти данные покупают у владельцев.
Это действительно один из самых мощных способов снизить риск "вложить кучу денег в открытие, но прогадать с местом", а автоматизация процесса поиска потенциальных мест открытия и их анализа помогает быстрее масштабировать сеть. Федеральные сети уже давно сформировали собственные отделы геоаналитики и активно закупают данные. Но как быть предпринимателям и микро бизнесу, который не готов тратить миллионы?
Если вы - аналитик, владеющий Python, который анализирует/прогнозирует потенциал локации или тот самый бизнес, который ищет место для открытия, а может просто любопытный прохожий, кот, бот - читайте до конца и дайте обратную связь в комментариях. Это моя первая статья, но, если понравится писать, будет продолжение=)
Гексагоны (H3: Uber’s Hexagonal Hierarchical Spatial Index)
Uber опубликовал open source проект, с помощью которого можно легко и просто нанести на карту красивые шестиугольники :) Подробнее.
Сделаем сразу импорт всех библиотек:
import geopandas as gpd
import pandas as pd
import numpy as np
import json
import h3
import folium
import osmnx as ox
from shapely import wkt
from folium.plugins import HeatMap
from shapely.geometry import Polygon
Посмотрим как выглядит гексагон для рандомной точки в г. Краснодар:
def visualize_hexagons(hexagons, color="red", folium_map=None):
polylines = []
lat = []
lng = []
for hex in hexagons:
polygons = h3.h3_set_to_multi_polygon([hex], geo_json=False)
outlines = [loop for polygon in polygons for loop in polygon]
polyline = [outline + [outline[0]] for outline in outlines][0]
lat.extend(map(lambda v:v[0],polyline))
lng.extend(map(lambda v:v[1],polyline))
polylines.append(polyline)
if folium_map is None:
m = folium.Map(location=[sum(lat)/len(lat), sum(lng)/len(lng)], zoom_start=20, tiles='cartodbpositron')
else:
m = folium_map
for polyline in polylines:
my_PolyLine=folium.PolyLine(locations=polyline,weight=8,color=color)
m.add_child(my_PolyLine)
return m
h3_address = h3.geo_to_h3(45.035470, 38.975313, 9) # 9 - индекс, определяющий размер гексагона
visualize_hexagons([h3_address])
OSM
OSM или Open Street Map - это открытый ресурс с геоданными по всему миру. Подробнее о проекте.
Подробнее про объекты карты, которые мы будем выгружать и анализировать.
Теперь, с помощью osmnx и h3 сотворим магию и сгенерим гексагоны внутри полигона г. Краснодара:
1) Выгрузим границы г. Краснодара из OSM
def visualize_polygons(geometry):
lats, lons = get_lat_lon(geometry)
m = folium.Map(location=[sum(lats)/len(lats), sum(lons)/len(lons)], zoom_start=13, tiles='cartodbpositron')
overlay = gpd.GeoSeries(geometry).to_json()
folium.GeoJson(overlay, name = 'boundary').add_to(m)
return m
# выводим центроиды полигонов
def get_lat_lon(geometry):
lon = geometry.apply(lambda x: x.x if x.type == 'Point' else x.centroid.x)
lat = geometry.apply(lambda x: x.y if x.type == 'Point' else x.centroid.y)
return lat, lon
# выгрузим границы Краснодара из OSM
cities = ['Краснодар']
polygon_krd = ox.geometries_from_place(cities, {'boundary':'administrative'}).reset_index()
polygon_krd = polygon_krd[(polygon_krd['name'] == 'городской округ Краснодар')]
# посмотрим что получилось
visualize_polygons(polygon_krd['geometry'])
2) Сгенерим гексагоны внутри полигона:
def create_hexagons(geoJson):
polyline = geoJson['coordinates'][0]
polyline.append(polyline[0])
lat = [p[0] for p in polyline]
lng = [p[1] for p in polyline]
m = folium.Map(location=[sum(lat)/len(lat), sum(lng)/len(lng)], zoom_start=13, tiles='cartodbpositron')
my_PolyLine=folium.PolyLine(locations=polyline,weight=8,color="green")
m.add_child(my_PolyLine)
hexagons = list(h3.polyfill(geoJson, 8))
polylines = []
lat = []
lng = []
for hex in hexagons:
polygons = h3.h3_set_to_multi_polygon([hex], geo_json=False)
# flatten polygons into loops.
outlines = [loop for polygon in polygons for loop in polygon]
polyline = [outline + [outline[0]] for outline in outlines][0]
lat.extend(map(lambda v:v[0],polyline))
lng.extend(map(lambda v:v[1],polyline))
polylines.append(polyline)
for polyline in polylines:
my_PolyLine=folium.PolyLine(locations=polyline,weight=3,color='red')
m.add_child(my_PolyLine)
polylines_x = []
for j in range(len(polylines)):
a = np.column_stack((np.array(polylines[j])[:,1],np.array(polylines[j])[:,0])).tolist()
polylines_x.append([(a[i][0], a[i][1]) for i in range(len(a))])
polygons_hex = pd.Series(polylines_x).apply(lambda x: Polygon(x))
return m, polygons_hex, polylines
# polygon_hex , polylines - геометрии гексагонов в разных форматах
# сгенерим гексагоны внутри полигона г. Краснодар
geoJson = json.loads(gpd.GeoSeries(polygon_krd['geometry']).to_json())
geoJson = geoJson['features'][0]['geometry']
geoJson = {'type':'Polygon','coordinates': [np.column_stack((np.array(geoJson['coordinates'][0])[:, 1],
np.array(geoJson['coordinates'][0])[:, 0])).tolist()]}
m, polygons, polylines = create_hexagons(geoJson)
m
Выгрузка, визуализация и анализ геоданных из OSM
Выгружаем объекты карты из OSM:
def osm_query(tag, city):
gdf = ox.geometries_from_place(city, tag).reset_index()
gdf['city'] = np.full(len(gdf), city.split(',')[0])
gdf['object'] = np.full(len(gdf), list(tag.keys())[0])
gdf['type'] = np.full(len(gdf), tag[list(tag.keys())[0]])
gdf = gdf[['city', 'object', 'type', 'geometry']]
print(gdf.shape)
return gdf
# Выгрузим интересующие нас категории объектов
tags = [
{'building' : 'apartments'}, {'building' : 'detached'},
{'building' : 'dormitory'}, {'building' : 'hotel'},
{'building' : 'house'}, {'building' : 'semidetached_house'},
{'building' : 'terrace'}, {'building' : 'commercial'},
{'building' : 'office'}, {'building' : 'terrace'},
{'building' : 'terrace'}, {'building':'retail'},
{'building':'train_station'},
{'highway' : 'bus_stop'}, {'footway':'crossing'},
{'amenity':'cafe'}, {'amenity':'fast_food'},
{'amenity':'restaurant'}, {'amenity':'college'},
{'amenity':'language_school'}, {'amenity':'school'},
{'amenity':'university'}, {'amenity':'atm'},
{'amenity':'bank'}, {'amenity':'clinic'},
{'amenity':'hospital'}, {'amenity':'pharmacy'},
{'amenity':'theatre'}, {'amenity':'townhall'},
{'amenity':'bench'},
]
cities = ['Краснодар, Россия']
gdfs = []
for city in cities:
for tag in tags:
gdfs.append(osm_query(tag, city))
# посмотрим что получилось
data_poi = pd.concat(gdfs)
data_poi.groupby(['city','object','type'], as_index = False).agg({'geometry':'count'})
# добавим координаты/центроиды
lat, lon = get_lat_lon(data_poi['geometry'])
data_poi['lat'] = lat
data_poi['lon'] = lon
Spatial Join
Теперь, нам надо сджойнить полученные объекты с гексагонами:
# sjoin - spatial join - пересекаем гексагоны с объектами (определяем какие объекты находятся в разрезе каждого гексагона)
gdf_1 = gpd.GeoDataFrame(data_poi, geometry=gpd.points_from_xy(data_poi.lon, data_poi.lat))
gdf_2 = pd.DataFrame(polygons, columns = ['geometry'])
gdf_2['polylines'] = polylines
gdf_2['geometry'] = gdf_2['geometry'].astype(str)
geometry_uniq = pd.DataFrame(gdf_2['geometry'].drop_duplicates())
geometry_uniq['id'] = np.arange(len(geometry_uniq)).astype(str)
gdf_2 = gdf_2.merge(geometry_uniq, on = 'geometry')
gdf_2['geometry'] = gdf_2['geometry'].apply(wkt.loads)
gdf_2 = gpd.GeoDataFrame(gdf_2, geometry='geometry')
itog_table = gpd.sjoin(gdf_2, gdf_1, how='left', op='intersects')
itog_table = itog_table.dropna()
itog_table.head()
Посмотрим как по городу распределены кофейни:
def create_choropleth(data, json, columns, legend_name, feature, bins):
lat, lon = get_lat_lon(data['geometry'])
m = folium.Map(location=[sum(lat)/len(lat), sum(lon)/len(lon)], zoom_start=13, tiles='cartodbpositron')
folium.Choropleth(
geo_data=json,
name="choropleth",
data=data,
columns=columns,
key_on="feature.id",
fill_color="YlGn",
fill_opacity=0.7,
line_opacity=0.2,
legend_name=legend_name,
nan_fill_color = 'black',
bins = bins
).add_to(m)
folium.LayerControl().add_to(m)
return m
# подготовим данные
itog_table['geometry'] = itog_table['geometry'].astype(str) #для groupby
itog_table['id'] = itog_table['id'].astype(str) #для Choropleth
agg_all = itog_table.groupby(['geometry','type','id'], as_index = False).agg({'lat':'count'}).rename(columns = {'lat':'counts'})
agg_all['geometry'] = agg_all['geometry'].apply(wkt.loads) #возвращаем формат геометрий
agg_all_cafe = agg_all.query("type == 'cafe'")[["geometry","counts",'id']]
agg_all_cafe['id'] = agg_all_cafe['id'].astype(str)
data_geo_1 = gpd.GeoSeries(agg_all_cafe.set_index('id')["geometry"]).to_json()
create_choropleth(agg_all_cafe, data_geo_1, ["id","counts"], 'Cafe counts', 'counts', 5)
Выгрузим доступную инфу о жилых многоэтажных зданиях:
gdf_aparts = ox.geometries_from_place(city, {'building' : 'apartments'}).reset_index()
# полнота building:levels (этажи)
print(np.round(len(gdf_aparts['building:levels'].dropna())/len(gdf_aparts['building:levels']), 2))
# полнота building:flats (квартиры)
print(np.round(len(gdf_aparts['building:flats'].dropna())/len(gdf_aparts['building:flats']), 2))parts['building:flats'].dropna())/len(gdf_aparts['building:flats']), 2)
Давайте посчитаем сколько людей проживает в этих домах, основываясь на следующих предположениях:
Ok, Гугл: сколько в среднем квартир на этаже?
Гугл вещает, что кол-во квартир напрямую зависит от класса жилья:
эконом - в среднем 10
комфорт - в среднем 6-8
бизнес - в среднем 4-6
Мы можем (как отчаянные дата - сатанисты) углубиться в эту тему и парсить объявления авито/циан и на основе стоимости 1 кв. м определять класс объекта, да и данных по объектам недвижимости будет больше, чем с OSM
Но мы здесь собрались не для того, чтобы парсить авито/циан, поэтому дальше будем использовать в среднем 10 квартир на этаж (доля бизнес и комфорт класса не так велика в Краснодаре)
# добавим фичу - население
lat_g, lon_g = get_lat_lon(gdf_aparts['geometry'])
gdf_aparts['lat'] = lat_g
gdf_aparts['lon'] = lon_g
itog_table_people = itog_table.merge(gdf_aparts[['lat', 'lon', 'building:levels']], on = ['lat', 'lon'], how = 'left')
itog_table_people['building:levels'] = itog_table_people['building:levels'].fillna(1)
itog_table_people = itog_table_people.rename(columns = {'building:levels' : 'levels'})
apartments = ['apartments' , 'dormitory']
houses = ['house', 'semidetached_house', 'detached', 'terrace']
people_ctn = []
# в среднем возьмем 3 чел. на семью
for i in range(len(itog_table_people)):
if itog_table_people['type'].iloc[i] in apartments:
people = int(itog_table_people['levels'].iloc[i])*10*3
elif itog_table_people['type'].iloc[i] in houses:
people = int(itog_table_people['levels'].iloc[i])*3
else:
people = 'not living area'
people_ctn.append(people)
itog_table_people['count_people'] = people_ctn
table_people = itog_table_people.query("count_people != 'not living area'")
table_people['count_people'] = table_people['count_people'].astype(int)
Посмотрим что у нас вышло с плотностью "гипотетического" населения в Краснодаре:
def create_heatmap(data, lat_lon_feature):
m = folium.Map(location=[sum(data['lat'])/len(data['lat']), sum(data['lon'])/len(data['lon'])], zoom_start=13, tiles='cartodbpositron')
HeatMap(data[lat_lon_feature].groupby(lat_lon_feature[0:2]).sum().reset_index().values.tolist(),
radius = 70, min_opacity = 0.05, max_val = int((data[lat_lon_feature[2]]).quantile([0.75])), blur=30).add_to(m)
return m
# карта плотности населения
create_heatmap(table_people, ['lat', 'lon', 'count_people'])
Где открыть кофейню? Определяем лучшее место для поиска потенциального помещения
Где открыть кофейню? Вопрос для отдельной статьи, а сюда я пришла, чтобы показать вам пример как можно творить магию геаналитику на открытых данных. Логично, что одним из ключевых факторов будет много людей и мало конкурентов, т. е. я предлагаю вам рассчитать фичу население/кол-во кофеен в гексагоне. Так мы сможем выбрать ТОП гексагоны для поиска потенциальных мест для открытия кофейни. Итого:
Добавим фичу население/кол-во кофеен в гексагоне.
Выберем гексагон с наибольшим значением.
Выберем этот гексагон и его 6 соседей (быстро это можно сделать с помощью KDTree библиотеки scipy), чтобы на всякий пожарный не упустить ближайшие области из-за каких-либо перекосов в данных OSM (опционально).
Открываем авито/циан и ищем там помещение для кофейни.
Какие еще фичи можно рассчитать?
Количество якорей трафика (ТЦ, БЦ, фаст фуд рестораны, супермаркеты и т. д.) поделим на кол-во кофеен/на кол-во населения
Huff (а вот про модель Huff я расскажу позже :)
Моя первая статья на Habr. Не кидайте помидоры :)
Комментарии (35)
molec
25.09.2021 12:11Огромное спасибо за статью! Я бы сам до шестиугольников еще долго не дошёл, хотя с географией работаю.
Пс. Главное, чтобы никто не бросился по этой тепловой карте строить кофейни в Краснодарском Шанхае ;)
mentin
26.09.2021 09:05Просьба, если уж включаете в статью код, проверять что он хоть чуть-чуть работает.
Видимо, делалось все в Jupiter, где куча всякого хлама остается в контексте, и можно итеративно использовать переменные созданные ниже или раньше, но стоит запустить код чистом режиме, и проверить, чтобы такой хлам не попадал в статью.
Откуда
hexagons
в самом начале вfor hex in hexagons :
, к этому моменту был только один шестиугольникh3_address
. Мистически появились из четвертого куска кода (мы во втором).Почему
get_lat_lon_
вызывается с подчеркиванием на конце, а определено без?Что за
geometry
используется вoverlay = gpd.GeoSeries(geometry).to_json()
- до этогоgeometry
была только локальной переменной и не присутствует в текущем скоупе, переменной с таким именем нет даже ниже.
Такой подход к коду оставляет впечатление жуткой неаккуратности (к которой на мой взгляд приучает Jupiter, но это для другой статьи).
TatianaLi Автор
26.09.2021 16:57Спасибо большое за замечания, уже редактирую, сегодня обновлю статью!
Не ругайтесь на юпитер) вы, как я поняла, разработчик, поэтому я прекрасно понимаю о чем вы)
boggis30
22.10.2021 19:58Очень интересно, узнал из статьи и из комментариев про индексирование шестиугольниками. Спасибо!
PastorGL
Привет, коллега. Неплохо для вводной статьи.
Надеюсь, последуют ещё статьи, и вы расскажете, что для открытия кофейни в каком-нить райончике необходимо знать не только кол-во населения и плотность заведений, но и типичный паттерн перемещений в интересующей области. Гуляют ли там люди, или, например, проезжают мимо. И, главное, есть ли у них принципиальный интерес её посетить, — который, как показывает практика, вполне вычислим.
Расскажете вашу версию? (Я вот, к сожалению, наш патентованный метод из-за NDA не могу озвучить.)
TatianaLi Автор
Привет! Спасибо большое за обратную связь! Планируется еще не 1 статья, так как тема действительно очень обширная и есть чем поделиться (эх, если бы и правда все было так просто - открыть там, где много людей:))
TatianaLi Автор
раскрыть всю внутренность как это происходит при работе с биг датой я конечно тоже не могу, но буду делиться другими фишками, которые можно использовать малому бизнесу)
PastorGL
Ну, мой проект уже 5 лет занимается задачами геоинформационной аналитики.
Так что я могу со знанием дела подтвердить, что задачи на классификацию/типирование/скоринг/профилирование популяций и потоков людей — это крайне интересные и достаточно сложные задачи.
Главное, никто до сих пор не научился решать их с приемлемым соотношением стоимость/качество (все overpromising, но underdelivering), поэтому любое знание тут ценно.
sshikov
>Главное, никто до сих пор не научился решать их с приемлемым соотношением стоимость/качество
Да тут полно проблем. Минимум одна из которых вообще не решается одной аналитикой: для начала нужно иметь что анализировать. Т.е. исходные данные, если уж совсем просто (и даже не обязательно потоки людей, а просто статические данные). Ну т.е. если вернуться к кейсу «открыть кофейню», то очевидно нужны данные сразу нескольких видов:
* где можно открыть (данные об аренде помещений в этом районе)
* стоимость аренды
* есть ли в этом месте достаточный поток потенциальных клиентов
* что именно нужно этим клиентам
* а есть ли конкуренты, и как они вообще себя чувствуют?
И в общем априори очевидно, что это данные далеко не из одного источника. В итоге, их не просто сложно собрать, но еще и сложно сопосотавить друг с другом. Автор, как я понимаю, в Билайне (и как у сотового оператора, есть данные по людям и их перемещениям), я смотрел на это когда-то со стороны банка (и были данные по транзакциям), но даже если вы Билайн или банк с кучей клиентов — у вас все равно далеко не всегда есть все данные. Скажем — данные по конкурентам — тот же Билайн вероятно может их только купить (у Яндекса, Гугля, 2ГИС и т.п.). И даже если вы банк — как только конкурент обслуживается не у вас, вы уже очень мало про него знаете.
И возможно, по именно этой причине у автора разбор кейса с кофейней (возможно, пока), заканчивается на самом интересном месте:
Так а где сравнение помещений в пределах района? Может, я что-то упустил в тексте, но на мой взгляд, разница в посещаемости между двумя кофейнями (я привычно примеряю на свой район) в торговом центре у метро и в двух кварталах от него (т.е. 100 метров) — возможно где-то на порядок.
PastorGL
Да данные-то есть. Сотовые операторы, банки, рекламные сети, и все кто угодно продают их через агрегаторы в деперсонифицированном виде с превеликим удовольствием. Про это я писал в своей статье уже скоро пару лет назад, а с тех пор ничего не поменялось. Но стоят они дорого, а качество зачастую паршивое. Что тоже ни фига не меняется.
Поэтому, чтобы их сопоставить, и извлечь полезные знания, приходится заниматься некоторой алгоритмической эквилибристикой. Очень большой простор для изобретения всяких эвристик и enrichment mechanics.
Плюс ко всему, все теоретические модели хорошо работают только на том сэмпле, на котором их, собственно, и моделировали. Что хорошо работает в Америке, то в Европе показывает ерунду, и наоборот.
Эх, если бы мне только можно было рассказать подробности наших методик, я б десяток статей тут настрочил. К сожалению, коммерческая тайна.
sshikov
>Но стоят они дорого, а качество зачастую паршивое.
Так а я о чем? Данные есть в разных источниках, сопоставить их друг с другом сложно, потому что см. выше. Ну т.е. это одна из проблем — возможно решаемая, но реальная.
>простор для изобретения всяких эвристик
Чем наши сайентисты большую часть времени и занимались. Т.е. упрощенно — вот у вас есть транзакции, и вы хотите понять, чего потребитель купил там или там (чтобы оценить саму потребность в кофейне). И выясняется, что транзакции-то — они из VISA, например, и мерчант (и его адрес) там записан в некоторой латинской транскрипции, которую фиг сопоставишь с любой из карт (т.е. процессы геокодирования становятся совершенно ненадежными). Т.е. мы не можем по транзакции зачастую понять, где купили, а что купили — там просто не пишется.
В итоге транзакции достаточно просто сопоставляются только в одном случае — если вы банк, и это ваша карточка, а еще в кафешке стоит POS от вас же (что очевидно далеко не всегда так). В остальных случаях уже тоже начинались эвристики.
>подробности наших методик
Ну так именно это и интересно, конечно же :) И конкурентам вашим — в первую очередь.
TatianaLi Автор
Очень все индивидуально (в плане данных/алгоритма/точности и т. д.) для каждого формата/заказчика. Но факт, что даже модель "на коленке" может улучшить работу отдела развития (те ребята, которые ищут коммерческие помещения и т. д.) - это факт. Чем крупнее компания и соответственно обучающая выборка и ресурсы, тем лучше результат конечно, от этого никуда не денешься... а мэтчинг транзакций мало кто использует, слишком это дорого и эффект не оправдывает себя
sshikov
>мэтчинг транзакций мало кто использует
Ну мы пробовали. Помимо всего прочего, это персональные данные со всеми вытекающими. Тут нужно сильно стараться, чтобы они в таком персональном виде не вытекли куда-то случайно, а это тоже да, дорого. Да и много их, тут уже реально большие данные начинают иметь место.
PastorGL
А мы даже с удовольствием бы всю нашу алгоритмику и методику продавали кому угодно, но «конкуренты» почему-то хотят всё сделать сами, вместо того чтобы готовое взять %) Странно это. Никто не хочет верить чужим эвристикам, видимо.
Пока что только с Precisely договорились, чтобы augment'ить ихний социодем по Европе. По Америке вот не получается, там качество сырых данных такое, что 99% сразу уходит в шлак.
sshikov
>Никто не хочет верить чужим эвристикам, видимо.
Возможно. А может быть у них просто другой набор доступных данных и несколько другие задачи, и они не уверены, что что-то получится на чужих эвристиках.
sshikov
Честно говоря, какой-то код на питоне — чуть ли не последнее, что хотелось бы видеть в статье обзорного плана. Ну, во всяком случае на мой взгляд. Те кто этой темой уже занимается (и даже такие как я, кто уже три года как бросил и занят другой), уже вероятно нашли свой инструмент, и уж что такое OSM, вероятно знают давно. И ЦИАН тоже парсили :)
Лучше бы ближе к бизнесу, если можно так выразиться, и чуть выше уровнем.
TatianaLi Автор
Спасибо за обратную связь! Статья как раз рассчитана на новичков, "прожженным" аналитикам в сфере гео будет скучно, согласна)
PastorGL
Тема очень уж узкоспециализированная, новичков в неё фиг заманишь %)
mentin
Код на питоне - отлично. Мне делающему это на SQL интересно как это в параллельной вселенной :).
Кстати, а зачем spatial join шестиугольников с точками? Думаю здесь гораздо быстрее для каждой точки посчитать номер шестиугольника и сделать обычный джоин по номерам шестиугольников, нет?
TatianaLi Автор
Спасибо!
TatianaLi Автор
Пространственные индексы используются в предназначенных для работы с его данными базах как раз для оптимизации расчетов. Вручную с помощью python это делать смысла нет, когда есть библиотека GeoPandas
mentin
Пространственные индексы великая вещь, когда вы работаете с произвольными фигурами, например полигонами территорий, линиями дорог. Но они в любом случае сравнительно медленные, по сравнению с хеш-таблицами. Убер свои шестиугольники создал именно как индекс, потому что (при масштабе Убера) универсальный пространственный индекс не справлялся.
Вы используете шестиугольники как удобную сетку, но не используете их основное предназначение как индекс. Когда всё уже проиндексировано шестиугольниками, совершенно естественно ими воспользоваться, а не индексировать заново универсальным индексом, который про специальные шестиугольники ничего знает, и будет работать с ними как с произвольными полигонами.
ne555
Хабр технический ресурс, а не бизнес инкубатор.
Автору за статью благодарность, позновательно!
sshikov
Если вам код такого типа интересен — то он уже сотни раз опубликован. Впрочем, мне совершенно не жалко, Я лишь свое мнение высказал, что идеи, которые этот код реализует, гораздо интереснее, потому что их мало хороших. А приведенный код расчета плотности населения… ну и что он вам дал полезного?
TatianaLi Автор
Понимаю ваш интерес, согласна, что можно было бы шире раскрыть тему. А про плотность населения на удивление не все в курсе) (опять таки, я говорю про небольшие компании, а не про специализированные отделы геоаналитики:)
sshikov
>про плотность населения на удивление не все в курсе
Я тут вижу пару аспектов:
— про шестиугольную сетку вы допустим рассказали, и показали какие-то расчеты, но вот почему собственно такая выбрана (а не обычная прямоугольная) — как-то я не вижу чтобы было написано (я если что, догадываюсь :).
— задача расчета плотности населения (как и любая частная задача) еще очень далека от реальной задачи оптимального размещения своего бизнеса в городе. То есть, на мой взгляд опять же, интереснее то, как можно получить практические выводы, тем более что тут все далеко не так очевидно, и не сводится к простой математике. Да и к сложной, в общем-то, тоже…
TatianaLi Автор
Спасибо!
Cleando
Будем ждать!
TatianaLi Автор
Спасибо!!!