数据经纬度匹配
我的数据是从链家网爬下来的数据,可以参考我的爬虫文章爬虫天津链家二手房数据(requests + BeautifulSoup)
其实链家有自己的经纬度,但是可能是网站加密的缘故,由于我技术有限,无法得到,就借助与高德API进行经纬度匹配
- 首先先去高德开发平台注册个账号(每天免费6000条,如果实名认证的话每天免费30w条数据,足够用了)
- 注册之后再应用界面创建新应用
名字随便写,没有什么问题 - 建好的应用选择添加选择web服务
之后我们就利用这个key来调高德API进行经纬度匹配
import time
import pandas as pd
import numpy as np
import json
import requests
import re
from bs4 import BeautifulSoup
def get_loc(data):
mc = data['小区名称']
location1 = '天津' + mc
loc = []
bases = r"https://restapi.amap.com/v3/geocode/geo?address="+location1+"&output=XML&key=你刚刚注册来的key"
for base in bases:
try:
response = requests.get(base)
soupi = BeautifulSoup(response.text,'lxml')
loc.append(soupi.find('location').text)
print('成功采集一条位置数据,共采集%i'%(len(loc)))
except:
try:
response = requests.get(base)
soupi = BeautifulSoup(response.text,'lxml')
loc.append(soupi.find('location').text)
print('成功采集一条位置数据,共采集%i'%(len(loc)))
except:
print('未成功采集两次,未成功采集的网址为',base)
loc.append(np.nan)
return loc
#locationplus = get_loc(data)
#data = pd.DataFrame()
#data['小区名称'] = ['市政府']
#data_use = data
if __name__ == "__main__":
#注意改路径
data = pd.read_excel(r'F:\I_love_learning\junior\数据挖掘与数据仓库\课程设计\dataxiaoqu.xlsx')
data = data[['单价','小区名称']]
data_use = data
locationplus = get_loc(data_use)
data_use['经纬度'] = locationplus
data_use['lng'] = data_use['经纬度'].str.split(',').str[0]
data_use['lat'] = data_use['经纬度'].str.split(',').str[1]
data_use.to_excel(r'F:\I_love_learning\junior\数据挖掘与数据仓库\课程设计\dataxiaoqu2.xlsx')
这样经纬度匹配就完事了
转换为WGS84坐标
如果你想用到QGIS作图和数据处理,需要转换为WGS84坐标
当然,直接用excel作图就不用转换,excel作图就是用的火星坐标
import json
import math
import pandas as pd
x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626 # π
a = 6378245.0 # 长半轴
ee = 0.00669342162296594323 # 扁率
def wgs84togcj02(lng, lat):
"""
WGS84转GCJ02(火星坐标系)
:param lng:WGS84坐标系的经度
:param lat:WGS84坐标系的纬度
:return:
"""
if out_of_china(lng, lat): # 判断是否在国内
return lng, lat
dlat = transformlat(lng - 105.0, lat - 35.0)
dlng = transformlng(lng - 105.0, lat - 35.0)
radlat = lat / 180.0 * pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
mglat = lat + dlat
mglng = lng + dlng
return [mglng, mglat]
def gcj02towgs84(lng, lat):
"""
GCJ02(火星坐标系)转GPS84
:param lng:火星坐标系的经度
:param lat:火星坐标系纬度
:return:
"""
#if out_of_china(lng, lat):
# return lng, lat
dlat = transformlat(lng - 105.0, lat - 35.0)
dlng = transformlng(lng - 105.0, lat - 35.0)
radlat = lat / 180.0 * pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
mglat = lat + dlat
mglng = lng + dlng
return [lng * 2 - mglng, lat * 2 - mglat]
def transformlat(lng, lat):
ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
math.sin(2.0 * lng * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(lat * pi) + 40.0 *
math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
math.sin(lat * pi / 30.0)) * 2.0 / 3.0
return ret
def transformlng(lng, lat):
ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
math.sin(2.0 * lng * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(lng * pi) + 40.0 *
math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
return ret
def out_of_china(lng, lat):
"""
判断是否在国内,不在国内不做偏移
:param lng:
:param lat:
:return:
"""
if lng <= 72.004 or lng >= 137.8347:
return True
if lat < 0.8293 or lat > 55.8271:
return True
return False
#loc_data = data_use
if __name__ == '__main__':
loc_data = pd.read_csv('F:\I_love_learning\junior\数据挖掘与数据仓库\课程设计\pro10data.csv')
lat = loc_data['lat'].tolist()
lng = loc_data['lng'].tolist()
result = []
for i in range(len(lng)):
result.append(gcj02towgs84(lng[i], lat[i]))
result_r = pd.DataFrame(result)
result_r.columns = ['lng','lat']
loc_data[['lat','lng']] = result_r
loc_data.to_csv('pro10data2.csv')
也可以匹配之后进行下数据预处理
# -*- coding: utf-8 -*-
"""
Created on Thu Mar 4 09:28:06 2021
@author: 89344
"""
import time
import pandas as pd
import numpy as np
import json
import requests
import re
from bs4 import BeautifulSoup
import json
import math
x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626 # π
a = 6378245.0 # 长半轴
ee = 0.00669342162296594323 # 扁率
def wgs84togcj02(lng, lat):
"""
WGS84转GCJ02(火星坐标系)
:param lng:WGS84坐标系的经度
:param lat:WGS84坐标系的纬度
:return:
"""
if out_of_china(lng, lat): # 判断是否在国内
return lng, lat
dlat = transformlat(lng - 105.0, lat - 35.0)
dlng = transformlng(lng - 105.0, lat - 35.0)
radlat = lat / 180.0 * pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
mglat = lat + dlat
mglng = lng + dlng
return [mglng, mglat]
def gcj02towgs84(lng, lat):
"""
GCJ02(火星坐标系)转GPS84
:param lng:火星坐标系的经度
:param lat:火星坐标系纬度
:return:
"""
#if out_of_china(lng, lat):
# return lng, lat
dlat = transformlat(lng - 105.0, lat - 35.0)
dlng = transformlng(lng - 105.0, lat - 35.0)
radlat = lat / 180.0 * pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
mglat = lat + dlat
mglng = lng + dlng
return [lng * 2 - mglng, lat * 2 - mglat]
def transformlat(lng, lat):
ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
math.sin(2.0 * lng * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(lat * pi) + 40.0 *
math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
math.sin(lat * pi / 30.0)) * 2.0 / 3.0
return ret
def transformlng(lng, lat):
ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
math.sin(2.0 * lng * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(lng * pi) + 40.0 *
math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
return ret
def out_of_china(lng, lat):
"""
判断是否在国内,不在国内不做偏移
:param lng:
:param lat:
:return:
"""
if lng <= 72.004 or lng >= 137.8347:
return True
if lat < 0.8293 or lat > 55.8271:
return True
return False
def data_cleaning2():
data = pd.read_excel(r'F:\I_love_learning\junior\数据挖掘与数据仓库\课程设计\dataxiaoqu2.xlsx')
data = data[['小区名称','单价','lng','lat']]
lat = data['lat'].tolist()
lng = data['lng'].tolist()
result = []
for i in range(len(lng)):
result.append(gcj02towgs84(lng[i], lat[i]))
result_r = pd.DataFrame(result)
result_r.columns = ['lng','lat']
data[['lng','lat']] = result_r
data['小区名称'] = data['小区名称'] + ' '
data.to_csv(r'F:\I_love_learning\junior\数据挖掘与数据仓库\课程设计\dataxiaoqu3.csv',encoding='utf-8')
if __name__ == "__main__":
data_cleaning2()
匹配好小区的经纬度之后,房屋的经纬度就唾手可得了
直接利用pandas中的连接方法即可获取
当然,重新匹配一遍也是可以的
# -*- coding: utf-8 -*-
"""
Created on Thu Mar 4 09:28:06 2021
@author: 89344
"""
import time
import pandas as pd
import numpy as np
import json
import requests
import re
from bs4 import BeautifulSoup
def data_cleaning1():
data = pd.read_excel(r'F:\I_love_learning\junior\数据挖掘与数据仓库\课程设计\dataroom.xlsx')
data['挂牌时间'] = data['挂牌时间'].str.split('间').str[1]
data['挂牌时间'] = pd.to_datetime(data['挂牌时间']).dt.date
location = pd.read_excel(r'F:\I_love_learning\junior\数据挖掘与数据仓库\课程设计\dataxiaoqu2.xlsx')
#去除\xa0
data_loc = pd.merge(data,location[['小区名称','lng','lat']],on = '小区名称')
data['总价'] = data['总价'].str.split('万').str[0].astype('float')
data['单价'] = data['单价'].str.split('元').str[0].astype('int')
data['面积'] = data['面积'].str.split('平').str[0].astype('float')
'''
m = data['所在区域']
mresu = []
for mi in m:
mi = ''.join(mi.split())
mresu.append(mi)
data['所在区域'] = mresu
data['经纬度'] = get_loc(data)
data['lng'] = data['经纬度'].str.split(',').str[0]
data['lat'] = data['经纬度'].str.split(',').str[1]
'''
data.to_excel(r'F:\I_love_learning\junior\数据挖掘与数据仓库\课程设计\dataroom2.xlsx')
'''
def get_loc(data):
mc = data['所在区域']+ data['小区名称']
location1 = '天津' + mc
loc = []
bases = r"https://restapi.amap.com/v3/geocode/geo?address="+location1+"&output=XML&key=a2d86849d5be62148caf5fd6cce5bf7d"
for base in bases:
try:
response = requests.get(base)
soupi = BeautifulSoup(response.text,'lxml')
loc.append(soupi.find('location').text)
print('成功采集一条位置数据')
except:
try:
response = requests.get(base)
soupi = BeautifulSoup(response.text,'lxml')
loc.append(soupi.find('location').text)
print('成功采集一条位置数据')
except:
print('未成功采集两次,未成功采集的网址为',base)
loc.append(np.nan)
return loc
'''
if __name__ == "__main__":
data_cleaning1()