Анализ для сравнения городов с использованием данных Foursquare и машинного обучения

Ключевые слова: наука о данных, машинное обучение, Python, просмотр веб-страниц, Foursquare

В сообщении рассказывается о методологии и анализе, использованных для финального проекта курса IBM Data Science Professional. Подробный отчет, код и результаты можно найти на Github, ссылка на них находится в конце публикации.

1. Введение

Выбор города, когда речь идет о Лондоне и Париже, всегда является трудным решением, поскольку оба эти города являются поистине глобальными, мультикультурными и космополитическими городами, расположенными в сердце двух европейских стран. Помимо того, что они являются двумя наиболее важными дипломатическими центрами Европы, они также являются крупными центрами финансов, торговли, науки, моды, искусства, культуры и гастрономии. И Лондон (столица Соединенного Королевства), и Париж (столица Франции) имеют богатую историю и являются двумя наиболее посещаемыми и востребованными городами Европы. Лондон является крупнейшим городом в Великобритании и стоит на реке Темзе в юго-восточной Англии. Париж, с другой стороны, расположен в северо-центральной части страны. Подобно Лондону, город также стоит вдоль реки, широко известной как река Сена.

Наша цель — провести сравнение двух городов, чтобы увидеть, насколько они похожи или непохожи. Такие методы позволяют пользователям идентифицировать похожие районы среди городов на основе удобств или услуг, предлагаемых на местном уровне, и, таким образом, могут помочь в понимании местной деятельности, каковы центры различных видов деятельности, как горожане воспринимают город и как они используют его. его ресурсы.

Какой клиентуре будет полезен такой анализ?

  1. Потенциальный соискатель с переносимыми навыками может пожелать искать работу в выбранных городах, которые обеспечивают наиболее подходящее соответствие его квалификации и опыту с точки зрения заработной платы, социальных пособий или даже с точки зрения культуры, подходящей для эмигрантов.
  2. Кроме того, человек, покупающий или арендующий дом в новом городе, может захотеть найти рекомендации о местах в городе, похожих на другие известные ему города.
  3. Аналогичным образом, такой анализ может принести пользу крупной корпорации, стремящейся расширить свое присутствие в других городах.
  4. Многие расчеты внутригородского городского планирования могут также выиграть от моделирования отношений города с другими городами.

2. Подготовка данных

Для решения поставленной задачи извлечение данных было сделано следующим образом:

Веб-скрапинг: данные о городах были извлечены из соответствующих страниц Википедии [1][2] с использованием библиотек Requests и BeautifulSoup.

## URL to extract City neighbourhood information
urlL = "https://en.wikipedia.org/wiki/List_of_London_boroughs"
urlP = "https://en.wikipedia.org/wiki/Arrondissements_of_Paris"
pageLondon = urllib.request.urlopen(urlL)
pageParis = urllib.request.urlopen(urlP)
wikitablesL = read_html(urlL,  attrs={"class":"wikitable"})
print ("Extracted {num} wikitables from London Wikipedia".format(num=len(wikitablesL)))
wikitablesP = read_html(urlP,  attrs={"class":"wikitable"})
print ("Extracted {num} wikitables from Paris Wikipedia".format(num=len(wikitablesP)))
dfP = wikitablesP[0]
dfL0 = wikitablesL[0]
dfL1 = wikitablesL[1]
## Request & response 
s = requests.Session()
responseL = s.get(urlL,timeout=10)

Дальнейшая очистка данных была выполнена на извлеченных данных, чтобы сохранить соответствующую информацию о его окрестностях, их соответствующих координатах, площади и населении, а также соответствующих номерах районов.

def scrapeLondonTable(table):
    c1=[]
    c2=[]
    c3=[]
    c4=[]
    c5=[]
    c6=[]
    c7=[]
    c8=[]
    c9=[]
    c10=[]
    c11=[]

    for row in table.findAll("tr"):
        cellsL = row.findAll('td')
        if len(cellsL)==10: #Only extract table body not heading
            c1.append(cellsL[0].find('a').text)
            c2.append(cellsL[1].find(text=True))   
            c3.append(cellsL[2].find(text=True))
            c4.append(cellsL[3].find(text=True))
            c5.append(cellsL[4].find(text=True))
            c6.append(cellsL[5].find(text=True))
            c7.append(cellsL[6].find(text=True))
            c8.append(cellsL[7].find(text=True))
            c9.append(cellsL[8].find('span',{'class': 'geo'}))
            c10.append(cellsL[9].find(text=True))
    # create a dictionary
    d = dict([(x,0) for x in headerL])
    # append dictionary with corresponding data list
    d['Borough'] = c1
    d['Inner']= c2
    d['Status']=c3
    d['Local authority']=c4
    d['Political control']=c5
    d['Headquarters']=c6
    d['Area (sq mi)']=c7
    d['Population (2013 est)[1]']=c8
    d['Co-ordinates']=c9
    d[' Nr. in map']=c10
    # convert dict to DataFrame
    dfL_table = pd.DataFrame(d)
    ## convert Area units to kms^2
    #dfL["Area"] = 2.59 * (pd.to_numeric(dfL["Area"]))
    Latitude = []
    Longitude = []
    for i in range(len(dfL_table)):
        locationSplit = dfL_table['Co-ordinates'].iloc[i].getText().split("; ") 
        Latitude.append(locationSplit[0])
        Longitude.append(locationSplit[1])
    dfL_table['Latitude'] = Latitude
    dfL_table['Longitude'] = Longitude
    dfL_table.drop(['Inner','Status','Local authority','Political control','Headquarters','Co-ordinates'],axis=1,inplace=True)
    dfL = dfL_table.rename(columns={'Area (sq mi)': 'Area', 'Population (2013 est)[1]': 'Population',' Nr. in map':'District Number'})
    dfL['District Number']  = dfL['District Number'].astype(int)
    for i in range(len(dfL)):
        dfL['Area'].iloc[i] = float(re.findall(r'[\d\.\d]+', dfL['Area'].iloc[i])[0])
        dfL['Population'].iloc[i] = int(dfL['Population'].iloc[i].replace(',',''))
    return dfL

После необходимой очистки данных мы получаем следующие кадры данных для нашего исследования:

Данные о местоположении Foursquare. Foursquare — это социальная служба определения местоположения, которая позволяет пользователям исследовать окружающий мир. API Foursquare предоставляет возможности на основе местоположения с разнообразной информацией о местах проведения, пользователях, фотографиях и регистрациях. Мы воспользовались данными Foursquare для извлечения информации о местах проведения мероприятий для всех исследуемых районов. Вызов API возвращает файл JSON, и нам нужно превратить его в фрейм данных. Затем данные о местоположении использовались для поиска лучших и уникальных мест в каждом районе. Я решил выбрать по 100 самых популярных мест в каждом районе в радиусе 1 км.

3. Исследовательский анализ данных

Данные города

Данные Википедии предоставили нам информацию о координатах, площади и населении каждого района в соответствующих городах. Эту информацию можно использовать для визуализации карты города с указанием каждого района в соответствии с его плотностью населения. Для визуализации данных на листовочных картах использовались библиотеки Геокодер и фолиум карта, где районы были отмечены в соответствии с их плотностью населения. Чем выше плотность, тем больше радиус маркера.

Данные о месте проведения

Данные о местоположении Foursquare дали информацию о списке мест в радиусе 1 км от каждого района. Это разумное расстояние, чтобы понять особенности района.

## Extracting Foursquare venue data
LIMIT = 100 # limit of number of venues returned by Foursquare API
radius = 1000 # define radius

def getNearbyVenues(names, latitudes, longitudes, radius=500):
    
    venues_list=[]
    for name, lat, lng in zip(names, latitudes, longitudes):
        print(name)
            
        # create the API request URL
        url = 'https://api.foursquare.com/v2/venues/explore?&client_id={}&client_secret={}&v={}&ll={},{}&radius={}&limit={}'.format(
            CLIENT_ID, 
            CLIENT_SECRET, 
            VERSION, 
            lat, 
            lng, 
            radius, 
            LIMIT)
            
        # make the GET request
        results = requests.get(url).json()["response"]['groups'][0]['items']

        # return only relevant information for each nearby venue
        venues_list.append([(
            name, 
            lat, 
            lng, 
            v['venue']['name'], 
            v['venue']['location']['lat'], 
            v['venue']['location']['lng'],  
            v['venue']['categories'][0]['name']) for v in results])
        
    nearby_venues = pd.DataFrame([item for venue_list in venues_list for item in venue_list])
    nearby_venues.columns = ['Borough', 
                  'Borough Latitude', 
                  'Borough Longitude', 
                  'Venue', 
                  'Venue Latitude', 
                  'Venue Longitude', 
                  'Venue Category']
    
    return(nearby_venues)
print("Getting venues inside the following Boroughs of London:")
London_venues = getNearbyVenues(names=tableL['Borough'],
                                   latitudes=tableL['Latitude'],
                                   longitudes=tableL['Longitude']
                                  )

В общей сложности было около 219 уникальных категорий площадок в Лондоне и 180 в Париже. Я использовал эту информацию, чтобы визуализировать наиболее распространенные места в некоторых центральных районах Лондона и Парижа на гистограмме.

## Picking major districts inside inner London and inner Paris respectively
districtsL = ['City of London','Westminster','Kensington and Chelsea','Hammersmith and Fulham', 'Wandsworth']
districtsP = ['Louvre, Bourse, Temple, Hôtel-de-Ville', 'Panthéon', 'Luxembourg', 'Palais-Bourbon', 'Élysée']

def nearbyvenues_count(venues_df, district):
    venues_count = venues_df
    venues_count = venues_count.rename(columns={'Venue Category': 'Category'})
    venues_count = venues_count.groupby(['Borough']).Category.value_counts().to_frame("Counts")
    fig, ax = plt.subplots(1,1,figsize=(20, 7)) 
    fig.subplots_adjust(left=0.115, right=0.88)
    venues_plot =  venues_count['Counts'].loc[district][:10].head(10) 
    pos = np.arange(len(venues_plot))
    ax.set_title(district,size=20)
    freqchart = ax.barh(pos, venues_plot,align='center',height=0.5,tick_label=venues_plot.index)
    
    return freqchart

В то время как наиболее распространенными заведениями в центре Лондона были кафе / кофейни, пабы, соки-бары или отели, наиболее распространенными местами проведения мероприятий в районах в центральных или крупных районах Парижа были в основном французские или итальянские рестораны, а также отели.

Чтобы изучить данные о месте проведения более всесторонним образом и использовать их для дальнейшего анализа, данные места проведения Foursquare были организованы во фрейм данных pandas следующим образом:

  • Во-первых, создайте кадр данных с горячей кодировкой pandas one для каждой из категорий площадок.
  • Получите среднее значение каждой категории мест с горячим кодированием, используя метод pandas groupby в столбце района.
  • Используйте среднее значение категории мест, чтобы получить базу данных на основе мест для каждого города, содержащую десять наиболее распространенных мест для каждого района.
## Categorizing venues into pandas
# one hot encoding
London_onehot = pd.get_dummies(London_venues[['Venue Category']], prefix="", prefix_sep="")

# add neighborhood column back to dataframe
London_onehot['Borough'] = London_venues['Borough'] 

# move neighborhood column to the first column
fixed_columns = [London_onehot.columns[-1]] + list(London_onehot.columns[:-1])
London_onehot = London_onehot[fixed_columns]
London_onehot.head()
London_grouped = London_onehot.groupby('Borough').mean().reset_index()
def return_most_common_venues(row, num_top_venues):
    row_categories = row.iloc[1:]
    row_categories_sorted = row_categories.sort_values(ascending=False)
    return row_categories_sorted.index.values[0:num_top_venues]
num_top_venues = 10
indicators = ['st', 'nd', 'rd']

# create columns according to number of top venues
columns = ['Borough']
for ind in np.arange(num_top_venues):
    try:
        columns.append('{}{} Most Common Venue'.format(ind+1, indicators[ind]))
    except:
        columns.append('{}th Most Common Venue'.format(ind+1))

# create a new dataframe for London
Londonboroughs_venues_sorted = pd.DataFrame(columns=columns)
Londonboroughs_venues_sorted['Borough'] = London_grouped['Borough']
for ind in np.arange(London_grouped.shape[0]):
    Londonboroughs_venues_sorted.iloc[ind, 1:] = return_most_common_venues(London_grouped.iloc[ind, :], num_top_venues)

Londonboroughs_venues_sorted.head(10)

Информация, содержащая наиболее распространенные данные о местах проведения мероприятий по районам, затем использовалась для разделения районов на кластеры с использованием k-средних.

4. Кластеризация окрестностей

Я выполнил кластерный анализ с использованием алгоритма k-means, чтобы разделить похожие районы на кластеры на основе сходства, обеспечиваемого категориями мест проведения. Чтобы получить некоторое представление, я решил провести небольшое исследование количества кластеров (k), которые будут использоваться следующим образом:

Метод локтя: я попытался определить эффективное количество кластеров (k) с помощью метода локтя для лондонского кластерного анализа и увидел небольшой излом около k = 6 (хотя и не четкий и резкий). Метод локтя использует внутрикластерную сумму квадратичных ошибок (WSS) для различных значений k, и можно выбрать значение k, при котором WSS начинает уменьшаться и может рассматриваться как локоть на графике WSS-против-k. Однако для парижских данных явно не было видно излома, поэтому я попытался изучить оценку силуэта для кластеризации для каждого значения k. Значение силуэта измеряет, насколько точка похожа на свой собственный кластер (сплоченность) по сравнению с другими кластерами (разделение). Значение около k = 2 дало глобальный максимум оценки силуэта. Хотя из этих исследований видно, что у нас нет четко сгруппированных данных, я решил разделить районы Лондона на 6 наборов кластеров, а районы Парижа — на 2 набора кластеров для целей нашего анализа. Возможно, было бы полезно изучить более подробный анализ, чтобы оптимизировать k в будущем для таких исследований.

5. Обсуждение результатов

Чтобы решить поставленную бизнес-задачу, мы рассмотрели 33 района внутреннего и внешнего Лондона и 16 районов внутреннего Парижа. Хотя каждый из этих районов может быть уникальным, некоторые из них могут быть более похожими с точки зрения предлагаемых удобств. Для поиска подобных окрестностей был проведен кластерный анализ. Следует отметить, что данные, извлеченные из London Wiki, давали информацию о районах во внутреннем и внешнем Лондоне и, таким образом, учитывали пригородную зону. В то время как данные, предоставленные Paris Wiki, давали информацию только о районах внутри Парижа и не включали много информации о больших пригородах, окружающих Париж, где проживает приличная часть населения. Таким образом, для анализа, проведенного в данном исследовании, потребуется больше информации для сравнения городов на равных условиях.

Некоторые из выводов, которые были сделаны из объяснительного анализа:

  • Большинство районов внутреннего Парижа более густонаселены, чем аналогичные районы внутреннего Лондона. В то время как в Лондоне есть 9 (из 33) районов с плотностью населения более 10 000 человек, только 3 района (из 16) в Париже имеют плотность менее 10 000 человек и 4 района выше 30 000 человек.
  • На карте густонаселенные районы более сконцентрированы во внутренних районах Лондона, чем во внешних регионах, а для Парижа самые густонаселенные районы расположены к северу от реки Сены.
  • Первоначальное изучение данных о местах проведения мероприятий Foursquare показало, что кофейни, кафе, пабы и фреш-бары являются наиболее распространенными заведениями в пяти основных районах Лондона. Точно так же французские рестораны, итальянские рестораны и отели были наиболее распространенными местами встречи в пяти основных районах внутреннего Парижа.

Кроме того, анализ данных о местах проведения с помощью машинного обучения показал, что большинство районов Лондона можно сгруппировать в один кластер. Наиболее распространенными местами встречи в таких районах всегда были кофейни, кафе, пабы, отели или рестораны, за которыми следовали какие-то магазины одежды, мини-маркеты или аптеки. Всего Париж был разделен на два отдельных кластера. Хотя наиболее распространенным местом встречи в обоих кластерах всегда был французский ресторан, за ним следовало большое количество итальянских ресторанов, отелей и кафе в первом кластере, а также варианты ресторанов, баров, бистро, магазинов одежды или супермаркетов другой кухни в других кластерах. второй кластер.

Наиболее распространенными типами заведений в любом из городов являются в основном рестораны, кафе, отели, пабы/бары, магазины одежды или парки. Это в некотором роде подчеркивает, насколько похожи города Лондона и Парижа с точки зрения предлагаемых услуг.

Можно дополнительно использовать данные о местах проведения для сравнения городов — это более комплексный способ, при котором можно также исследовать различные уровни пространственной агрегации, а именно сетки, районы и город в целом. Уровень пространственной агрегации может быть важным фактором при характеристике города с точки зрения его мест проведения.

Вот некоторые из вопросов, на которые можно ответить с помощью различных уровней пространственной агрегации:

  • Как распределяются категории объектов внутри района, т. Е. Район больше жилой или коммерческий.
  • В каком городе больше всего объектов инфраструктуры (баров, ресторанов, парков, университетов, библиотек, торговых центров и т. д.)?

6. Заключение

Подводя итог, можно сказать, что анализ городов с использованием данных Foursquare на основе мест проведения позволяет получить общее представление о типах мест проведения мероприятий в каждом районе и представить некоторые из ключевых особенностей городов, но уровень данных недостаточен для всестороннего анализа города. сравнение с городом. Для потенциального заинтересованного лица (ищущего работу или человека, решившего переехать в любой из городов) или более крупной клиентуры, такой как бизнес-корпорация или городские планировщики, потребуется провести более подробный анализ, добавив такие характеристики, как арендная плата, заработная плата, транспорт. , стоимость жизни, темпы роста, экономика и т. д.

Проект Capstone предоставил среду для более глубокого понимания того, как работают проекты по науке о данных в реальной жизни и какие шаги нужно предпринять для создания методологии науки о данных. Здесь подробно обсуждались все шаги от понимания бизнес-проблемы, понимания данных до подготовки данных и построения модели. Также были упомянуты многие недостатки текущего анализа и дальнейшие пути его улучшения. Это была первоначальная попытка понять и решить возникшую бизнес-проблему. Тем не менее, по-прежнему существует огромный потенциал для расширения этого проекта в реальных сценариях.

использованная литература

[1] Лондонская Википедия

[2] Парижская Википедия

Обо мне:

Я физик и уже несколько лет анализирую данные физики элементарных частиц. За последние несколько лет я переезжал по работе между Карлсруэ, Женевой, Сан-Паулу и Чикаго и в настоящее время проживаю в Париже. Хотя такой анализ данных был бы ступенькой для разработки методологии сравнения любого из городов, сравнение Лондона и Парижа было обусловлено личным выбором любви к этим городам. ❤

Больше обо мне можно узнать на Linkedin.

Ссылки на проект резюме и код.