莫斯科装修浪潮



美好的一天,habr的亲爱的读者们,在2020年8月12日,公布了翻新计划下的搬迁阶段(您可以在此处找到),我想知道如果这些阶段都可视化会怎样。在这里有必要澄清一下,我与莫斯科政府没有任何联系,但是我是一家装修建筑中的公寓的快乐主人,所以我很感兴趣地看到,也许甚至可以准确地猜出在我的情况下装修浪潮可能向何处移动(也许亲爱的读者,如果您对此感兴趣的话。当然,准确的预测是行不通的,但是至少可以从新的角度看图片。



UPD 2020年8月28日,我们

获得了一张完整的翻新地图,上面有翻新的波浪和发射场。



介绍



2017 . 350 , , .



, . 5174 .



… ( )



12 2020 . № 45/182/-335/20 ( ) 2032 ( ):



  • 2020 — 2024., 930 , 3-29
  • 2025 — 2028., 1636 , 30-76
  • 2029 — 2032., 1809 , 77-128
  • ( 1 2021.) — 688 , 129-148




github .



  • , . , .


wave1.ipynb (obsolete)



, .. — pdf , tabula pdf .



import pandas as pd
import numpy as np
import requests
from tabula import read_pdf
import json
import os


, , .



test = read_pdf('prikaz_grafikpereseleniya.pdf', pages='3', pandas_options={'header':None})


test.head()




0 1 2 3 4 5
0 No / NaN unom
1 1 ., .49 c.4 NaN 1316
2 2 ., .77 c.3 NaN 1327
3 3 ., .2/26 NaN 19328
4 4 ., .3 NaN 31354




, , , parse_pdf_table.



def parse_pdf_table(pages, pdf_file='prikaz_grafikpereseleniya.pdf'):
    df = read_pdf(pdf_file, pages=pages, pandas_options={'header':None})

    #    
    df = df[~(df.iloc[:,0] == 'No /')]

    #    
    df = df.iloc[:,1:4]
    df.columns = ['AO', 'district', 'address']

    return df


, , .. , pdf . ( , .. )



wave_1 = parse_pdf_table('3-29') # 2020 - 2024
wave_1['wave'] = 1


wave_1.shape


(930, 4)


wave_2 = parse_pdf_table('30-76') # 2025 - 2028
wave_2['wave'] = 2


wave_2.shape


(1636, 4)


wave_3 = parse_pdf_table('77-128') # 2029 - 2032
wave_3['wave'] = 3


wave_3.shape


(1809, 4)


unknown = parse_pdf_table('129-148')
unknown['wave'] = 0


unknown.shape


(688, 4)




(pandas), df.



df = pd.concat([wave_1, wave_2, wave_3, unknown], ignore_index=True)


.



df['marker-color'] = df['wave'].map({1:'#0ACF00',  # 
                                     2:'#1142AA',  # 
                                     3:'#FFFD00',  # 
                                     0:'#FD0006'}) # 


.



df['iconContent'] = df['wave'].map({1:'1',
                                    2:'2',
                                    3:'3',
                                    0:''})


.



df['description'] = df['address']


— , , , , , . ( ! :)





def add_city(x):
    if x['AO'] == '':
        return ', ' + x['address']

    return ', ' + x['address']


df['address'] = df[['AO', 'address']].apply(add_city, axis=1)


, , .. . , .



def geocoder(addr, key='  '):   
    url = 'https://geocode-maps.yandex.ru/1.x'
    params = {'format':'json', 'apikey': key, 'geocode': addr}
    response = requests.get(url, params=params)

    try:
        coordinates = response.json()["response"]["GeoObjectCollection"]["featureMember"][0]["GeoObject"]["Point"]["pos"]
        lon, lat = coordinates.split(' ')
    except:
        lon, lat = 0, 0

    return lon, lat


%%time
df['longitude'], df['latitude'] = zip(*df['address'].apply(geocoder))


CPU times: user 2min 11s, sys: 4.31 s, total: 2min 15s
Wall time: 15min 14s


( , .. , ), - - .



len(df[df['longitude'] == 0])


0


.



df.to_csv('waves.csv')


#df = pd.read_csv('waves.csv')




GeoJSON.



def df_to_geojson(df, properties, lat='latitude', lon='longitude'):
    geojson = {'type':'FeatureCollection', 'features':[]}
    for _, row in df.iterrows():
        feature = {'type':'Feature',
                   'properties':{},
                   'geometry':{'type':'Point',
                               'coordinates':[]}}
        feature['geometry']['coordinates'] = [row[lon],row[lat]]
        for prop in properties:
            feature['properties'][prop] = row[prop]
        geojson['features'].append(feature)
    return geojson


.. , , .



properties = ['marker-color', 'iconContent', 'description']

if not os.path.exists('data'):
    os.makedirs('data')

for ao, data in df.groupby('AO'):
    geojson = df_to_geojson(data, properties)

    with open('data/' + ao + '.geojson', 'w') as f:
        json.dump(geojson, f, indent=2) 


.geojson data. _.geojson .



geojson = df_to_geojson(df, properties)

with open('data/_.geojson', 'w') as f:
    json.dump(geojson, f, indent=2) 




( ) .





, , , , — (.), .1 - — . (. , .), .8//. ( , )



, :(



.



, . , , , , , , , . 39, , . 6, — , . 1, 2, 3, . 38.



( ), , , , .



— !





- , , / .





wave2.ipynb ( 2.0)

2.0



import pandas as pd
import numpy as np
import json
from tabula import read_pdf
from tqdm.notebook import tqdm
import os




with open('renovation_address.txt') as f:
    bounded_addresses = json.load(f)


def parse_pdf_table(pages, pdf_file='prikaz_grafikpereseleniya.pdf'):
    df = read_pdf(pdf_file, pages=pages, pandas_options={'header':None})

    #    
    df = df[~(df.iloc[:,0] == 'No /')]

    df['unom'] = df.iloc[:,-1].combine_first(df.iloc[:,-2])

    #    
    df = df.iloc[:,[1, 2, 3, -1]]
    df.columns = ['AO', 'district', 'description', 'unom']

    return df


wave_1 = parse_pdf_table('3-29') # 2020 - 2024
wave_1['wave'] = 1

wave_2 = parse_pdf_table('30-76') # 2025 - 2028
wave_2['wave'] = 2

wave_3 = parse_pdf_table('77-128') # 2029 - 2032
wave_3['wave'] = 3

unknown = parse_pdf_table('129-148')
unknown['wave'] = 0


df = pd.concat([wave_1, wave_2, wave_3, unknown], ignore_index=True)


df['marker-color'] = df['wave'].map({1:'#0ACF00',  # 
                                     2:'#1142AA',  # 
                                     3:'#FFFD00',  # 
                                     0:'#FD0006'}) # 

df['iconContent'] = df['wave'].map({1:'1',
                                    2:'2',
                                    3:'3',
                                    0:''})


df['longitude'] = 0
df['latitude'] = 0


for i in tqdm(bounded_addresses):
    unom = i['unom']
    coordinates = i['center']['coordinates']

    df.loc[df['unom']==unom, 'longitude'] = coordinates[1]
    df.loc[df['unom']==unom, 'latitude'] = coordinates[0]


HBox(children=(FloatProgress(value=0.0, max=5152.0), HTML(value='')))


#      , ..      
df.loc[(df['AO'] == '') | (df['AO'] == ''), 'AO'] = ''


df[df['longitude'] == 0]




AO district description unom wave marker-color iconContent longitude latitude
917 - . (.-), .11 15000016 1 #0ACF00 1 0.0 0.0
918 - . (.-), .13 15000015 1 #0ACF00 1 0.0 0.0
919 - . (.-), .3 15000013 1 #0ACF00 1 0.0 0.0
925 - . (.-), .4 15000012 1 #0ACF00 1 0.0 0.0
926 - . (.-), .6 15000014 1 #0ACF00 1 0.0 0.0
4883 . (. , .)... 4405823 0 #FD0006 0.0 0.0
4945 . (., /), .51 20000002 0 #FD0006 0.0 0.0
4946 . (., /), .52 20000003 0 #FD0006 0.0 0.0
4947 . (., /), .53 20000001 0 #FD0006 0.0 0.0
4948 . (., /), .85 20000000 0 #FD0006 0.0 0.0
4995 (.), .1 20000004 0 #FD0006 0.0 0.0




,



df.loc[917, ['longitude', 'latitude']] = 37.204805, 55.385382 
df.loc[918, ['longitude', 'latitude']] = 37.205255, 55.385367 
df.loc[919, ['longitude', 'latitude']] = 37.201518, 55.385265 
df.loc[925, ['longitude', 'latitude']] = 37.201545, 55.384927 
df.loc[926, ['longitude', 'latitude']] = 37.204151, 55.384576
df.loc[4883, ['longitude', 'latitude']] = 37.321218, 55.661308 
df.loc[4945, ['longitude', 'latitude']] = 37.476896, 55.604153 
df.loc[4946, ['longitude', 'latitude']] = 37.477406, 55.603895 
df.loc[4947, ['longitude', 'latitude']] = 37.476546, 55.602729 
df.loc[4948, ['longitude', 'latitude']] = 37.477568, 55.604659
df.loc[4995, ['longitude', 'latitude']] = 37.176806, 55.341541




with open('start_area.txt') as f:
    end = json.load(f)


data = {
    'AO':[],
    'district':[],
    'longitude':[],
    'latitude':[],
    'description':[]
}

for i in end['response']:

    data['AO'].append(i['OKRUG'])

    data['district'] = i['AREA']

    coordinates = i['geoData']['coordinates']

    data['longitude'].append(coordinates[1])
    data['latitude'].append(coordinates[0])

    description = i['Address']

    if 'StartOfRelocation' in i:
        if i['StartOfRelocation'] is not None:
            description += '\n' + i['StartOfRelocation']

    data['description'].append(description)

df_start_area = pd.DataFrame(data)
df_start_area['marker-color'] = '#7D3E00' #  
df_start_area['iconContent'] = '0'
df_start_area['unom'] = None
df_start_area['wave'] = -1




df = pd.concat([df, df_start_area], ignore_index=True)




def df_to_geojson(df, properties, lat='latitude', lon='longitude'):
    geojson = {'type':'FeatureCollection', 'features':[]}
    for _, row in df.iterrows():
        feature = {'type':'Feature',
                   'properties':{},
                   'geometry':{'type':'Point',
                               'coordinates':[]}}
        feature['geometry']['coordinates'] = [row[lon],row[lat]]
        for prop in properties:
            feature['properties'][prop] = row[prop]
        geojson['features'].append(feature)
    return geojson


properties = ['marker-color', 'iconContent', 'description']


.



if not os.path.exists('data'):
    os.makedirs('data')

for ao, data in df.groupby('AO'):
    geojson = df_to_geojson(data, properties)

    with open('data/' + ao + '.geojson', 'w') as f:
        json.dump(geojson, f, indent=2) 


( )



geojson = df_to_geojson(df, properties)

with open('data/_.geojson', 'w') as f:
    json.dump(geojson, f, indent=2) 




, , , , , , , .



UPD 28 2020



.



PbIXTOP , .



( )

























UPD 1 2020



隐藏了实现,添加了用于形成地图的最新代码,因为 本文的大多数读者只对地图感兴趣。



感谢您的关注。




All Articles